Skip to content

Commit a0254c9

Browse files
[SYCL] Use image pointer as a unique identifier for cache (#7113)
Currently different paths for building programs use different cache keys. Specifically, one path uses the kernel-set-id while another uses the pointer to the binary image. This may cause device binaries built by both paths may cause the programs to be rebuilt. Additionally, since the kernel-set-id may cover multiple device binaries, it may make colliding cache kernels. To fix the problems this commit will change the key use an image identifier rather than the kernel-set-id. We use the device binary pointer as the unique identifier. Signed-off-by: Larsen, Steffen <[email protected]>
1 parent e27fe82 commit a0254c9

File tree

3 files changed

+14
-8
lines changed

3 files changed

+14
-8
lines changed

sycl/source/detail/kernel_program_cache.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class KernelProgramCache {
6868
using PiProgramT = std::remove_pointer<RT::PiProgram>::type;
6969
using PiProgramPtrT = std::atomic<PiProgramT *>;
7070
using ProgramWithBuildStateT = BuildResult<PiProgramT>;
71-
using ProgramCacheKeyT = std::pair<std::pair<SerializedObj, KernelSetId>,
71+
using ProgramCacheKeyT = std::pair<std::pair<SerializedObj, std::uintptr_t>,
7272
std::pair<RT::PiDevice, std::string>>;
7373
using ProgramCacheT = std::map<ProgramCacheKeyT, ProgramWithBuildStateT>;
7474
using ContextPtr = context_impl *;

sycl/source/detail/program_manager/program_manager.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,10 @@ RT::PiProgram ProgramManager::getBuiltPIProgram(
640640

641641
const RT::PiDevice PiDevice = Dev->getHandleRef();
642642

643+
std::uintptr_t ImgId = reinterpret_cast<uintptr_t>(&Img);
643644
auto BuildResult = getOrBuild<PiProgramT, compile_program_error>(
644645
Cache,
645-
std::make_pair(std::make_pair(std::move(SpecConsts), KSId),
646+
std::make_pair(std::make_pair(std::move(SpecConsts), ImgId),
646647
std::make_pair(PiDevice, CompileOpts + LinkOpts)),
647648
AcquireF, GetF, BuildF);
648649
// getOrBuild is not supposed to return nullptr
@@ -1993,11 +1994,12 @@ device_image_plain ProgramManager::build(const device_image_plain &DeviceImage,
19931994
return BuiltProgram.release();
19941995
};
19951996

1997+
std::uintptr_t ImgId = reinterpret_cast<uintptr_t>(ImgPtr);
19961998
const RT::PiDevice PiDevice = getRawSyclObjImpl(Devs[0])->getHandleRef();
19971999
// TODO: Throw SYCL2020 style exception
19982000
auto BuildResult = getOrBuild<PiProgramT, compile_program_error>(
19992001
Cache,
2000-
std::make_pair(std::make_pair(std::move(SpecConsts), (size_t)ImgPtr),
2002+
std::make_pair(std::make_pair(std::move(SpecConsts), ImgId),
20012003
std::make_pair(PiDevice, CompileOpts + LinkOpts)),
20022004
AcquireF, GetF, BuildF);
20032005
// getOrBuild is not supposed to return nullptr
@@ -2022,7 +2024,7 @@ device_image_plain ProgramManager::build(const device_image_plain &DeviceImage,
20222024

20232025
getOrBuild<PiProgramT, compile_program_error>(
20242026
Cache,
2025-
std::make_pair(std::make_pair(std::move(SpecConsts), (size_t)ImgPtr),
2027+
std::make_pair(std::make_pair(std::move(SpecConsts), ImgId),
20262028
std::make_pair(PiDeviceAdd, CompileOpts + LinkOpts)),
20272029
AcquireF, GetF, CacheOtherDevices);
20282030
// getOrBuild is not supposed to return nullptr

sycl/unittests/kernel-and-program/MultipleDevsCache.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,13 +162,17 @@ TEST_F(MultipleDeviceCacheTest, ProgramRetain) {
162162
detail::KernelProgramCache::KernelCacheT &KernelCache =
163163
CtxImpl->getKernelProgramCache().acquireKernelsPerProgramCache().get();
164164

165-
EXPECT_EQ(KernelCache.size(), (size_t)2) << "Expect 2 kernels in cache";
165+
EXPECT_EQ(KernelCache.size(), (size_t)1)
166+
<< "Expect 1 program in kernel cache";
167+
for (auto &KernelProgIt : KernelCache)
168+
EXPECT_EQ(KernelProgIt.second.size(), (size_t)1)
169+
<< "Expect 1 kernel cache";
166170
}
167-
// First kernel creating is called in handler::single_task().
171+
// The kernel creating is called in handler::single_task().
168172
// kernel_bundle::get_kernel() creates a kernel and shares it with created
169173
// programs. Also the kernel is retained in kernel_bundle::get_kernel(). A
170174
// kernel is removed from cache if piKernelRelease was called for it, so it
171175
// will not be removed twice for the other programs. As a result we must
172-
// expect 3 piKernelRelease calls.
173-
EXPECT_EQ(KernelReleaseCounter, 3) << "Expect 3 piKernelRelease calls";
176+
// expect 2 piKernelRelease calls.
177+
EXPECT_EQ(KernelReleaseCounter, 2) << "Expect 2 piKernelRelease calls";
174178
}

0 commit comments

Comments
 (0)