diff --git a/opencl/doc/FAQ.md b/opencl/doc/FAQ.md index 8f381e5f67..fcedc442ff 100644 --- a/opencl/doc/FAQ.md +++ b/opencl/doc/FAQ.md @@ -56,7 +56,7 @@ which improves performance. ##### Environment flags (Linux only) -NEO_PERSISTENT_CACHE - integer value to enable (1)/disable (0) on-disk binary cache. When enabled +NEO_CACHE_PERSISTENT - integer value to enable (1)/disable (0) on-disk binary cache. When enabled Neo will try to cache and reuse compiled binaries. Default is off. NEO_CACHE_DIR - path to persistent cache directory. Default values are $XDG_CACHE_HOME/neo_compiler_cache diff --git a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp index 04dd451738..bee9c3fde8 100644 --- a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp @@ -2521,6 +2521,44 @@ TEST(OfflineCompilerTest, GivenGenBinaryWhenGenerateElfBinaryThenElfIsLoaded) { EXPECT_NE(0u, static_cast(mockOfflineCompiler->elfBinarySize)); } +TEST(OfflineCompilerTest, givenAllowCachingWhenBuildSourceCodeThenGenBinaryIsCachedUsingHashBasedOnNonNullIrBinary) { + std::vector argv = { + "ocloc", + "-file", + clFiles + "copybuffer.cl", + "-device", + gEnvironment->devicePrefix.c_str(), + "-allow_caching"}; + + auto mockOfflineCompiler = std::unique_ptr(new MockOfflineCompiler()); + ASSERT_NE(nullptr, mockOfflineCompiler); + auto retVal = mockOfflineCompiler->initialize(argv.size(), argv); + EXPECT_EQ(CL_SUCCESS, retVal); + + auto cacheMock = new CompilerCacheMock(); + mockOfflineCompiler->cache.reset(cacheMock); + retVal = mockOfflineCompiler->buildSourceCode(); + + EXPECT_EQ(CL_SUCCESS, retVal); + ASSERT_NE(nullptr, mockOfflineCompiler->irBinary); + ASSERT_NE(0u, mockOfflineCompiler->irBinarySize); + + // 0 - buildIrBinary > irBinary + // 1 - buildSourceCode > irBinary + // 2 - buildSourceCode > genBinary + // 3 - buildSourceCode > debugDataBinary + const auto givenCacheBinaryGenHash = cacheMock->cacheBinaryKernelFileHashes[2]; + const auto expectedCacheBinaryGenHash = cacheMock->getCachedFileName(mockOfflineCompiler->getHardwareInfo(), + ArrayRef(mockOfflineCompiler->irBinary, mockOfflineCompiler->irBinarySize), + mockOfflineCompiler->options, + mockOfflineCompiler->internalOptions, + std::string(mockOfflineCompiler->igcFacade->getIgcRevision()), + mockOfflineCompiler->igcFacade->getIgcLibSize(), + mockOfflineCompiler->igcFacade->getIgcLibMTime()); + + EXPECT_EQ(expectedCacheBinaryGenHash, givenCacheBinaryGenHash); +} + TEST(OfflineCompilerTest, WhenParsingCmdLineThenOptionsAreReadCorrectly) { std::vector argv = { "ocloc", diff --git a/shared/offline_compiler/source/offline_compiler.cpp b/shared/offline_compiler/source/offline_compiler.cpp index 590605df04..f2ca0ace68 100644 --- a/shared/offline_compiler/source/offline_compiler.cpp +++ b/shared/offline_compiler/source/offline_compiler.cpp @@ -331,26 +331,36 @@ int OfflineCompiler::buildSourceCode() { return INVALID_PROGRAM; } + const std::string igcRevision = igcFacade->getIgcRevision(); + const auto igcLibSize = igcFacade->getIgcLibSize(); + const auto igcLibMTime = igcFacade->getIgcLibMTime(); + if (allowCaching) { - const std::string igcRevision = igcFacade->getIgcRevision(); - const auto igcLibSize = igcFacade->getIgcLibSize(); - const auto igcLibMTime = igcFacade->getIgcLibMTime(); irHash = cache->getCachedFileName(getHardwareInfo(), sourceCode, options, internalOptions, igcRevision, igcLibSize, igcLibMTime); irBinary = cache->loadCachedBinary(irHash, irBinarySize).release(); genHash = cache->getCachedFileName(getHardwareInfo(), ArrayRef(irBinary, irBinarySize), options, internalOptions, igcRevision, igcLibSize, igcLibMTime); genBinary = cache->loadCachedBinary(genHash, genBinarySize).release(); + const bool generateDebugInfo = CompilerOptions::contains(options, CompilerOptions::generateDebugInfo); + if (generateDebugInfo) { + dbgHash = cache->getCachedFileName(getHardwareInfo(), irHash, options, internalOptions, igcRevision, igcLibSize, igcLibMTime); + debugDataBinary = cache->loadCachedBinary(dbgHash, debugDataBinarySize).release(); + } + if (irBinary && genBinary) { - if (!CompilerOptions::contains(options, CompilerOptions::generateDebugInfo)) + bool isZebin = isDeviceBinaryFormat(ArrayRef(reinterpret_cast(genBinary), genBinarySize)); + + auto asBitcode = ArrayRef::fromAny(irBinary, irBinarySize); + isSpirV = NEO::isSpirVBitcode(asBitcode); + + if (!generateDebugInfo) { + return retVal; + } else if (debugDataBinary || isZebin) { return retVal; - else { - dbgHash = cache->getCachedFileName(getHardwareInfo(), irHash, options, internalOptions, igcRevision, igcLibSize, igcLibMTime); - debugDataBinary = cache->loadCachedBinary(dbgHash, debugDataBinarySize).release(); - if (debugDataBinary) - return retVal; } } + delete[] irBinary; delete[] genBinary; irBinary = nullptr; @@ -399,6 +409,7 @@ int OfflineCompiler::buildSourceCode() { storeBinary(debugDataBinary, debugDataBinarySize, igcOutput->GetDebugData()->GetMemory(), igcOutput->GetDebugData()->GetSizeRaw()); } if (allowCaching) { + genHash = cache->getCachedFileName(getHardwareInfo(), ArrayRef(irBinary, irBinarySize), options, internalOptions, igcRevision, igcLibSize, igcLibMTime); cache->cacheBinary(irHash, irBinary, static_cast(irBinarySize)); cache->cacheBinary(genHash, genBinary, static_cast(genBinarySize)); cache->cacheBinary(dbgHash, debugDataBinary, static_cast(debugDataBinarySize)); diff --git a/shared/test/common/mocks/mock_compiler_cache.h b/shared/test/common/mocks/mock_compiler_cache.h index eee6cabe61..47433dbad5 100644 --- a/shared/test/common/mocks/mock_compiler_cache.h +++ b/shared/test/common/mocks/mock_compiler_cache.h @@ -19,6 +19,7 @@ class CompilerCacheMock : public CompilerCache { bool cacheBinary(const std::string &kernelFileHash, const char *pBinary, size_t binarySize) override { cacheInvoked++; + cacheBinaryKernelFileHashes.push_back(kernelFileHash); return cacheResult; } @@ -31,6 +32,7 @@ class CompilerCacheMock : public CompilerCache { return nullptr; } + std::vector cacheBinaryKernelFileHashes{}; bool cacheResult = false; uint32_t cacheInvoked = 0u; bool loadResult = false;