From 2f2684004b86cc3f6501b260205d17bf2aa647a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20=C5=9Alusarczyk?= Date: Fri, 28 Nov 2025 11:19:30 +0100 Subject: [PATCH] [SYCL] avoid taking lock and waiting in common path of KernelProgramCache::getOrBuild --- sycl/source/detail/kernel_program_cache.hpp | 27 +++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/sycl/source/detail/kernel_program_cache.hpp b/sycl/source/detail/kernel_program_cache.hpp index 645a49f7ded47..55919b74a6e3f 100644 --- a/sycl/source/detail/kernel_program_cache.hpp +++ b/sycl/source/detail/kernel_program_cache.hpp @@ -90,15 +90,10 @@ class KernelProgramCache { /// A mutex to be employed along with MBuildCV. std::mutex MBuildResultMutex; - BuildState - waitUntilTransition(BuildState From = BuildState::BS_InProgress) { - BuildState To; + BuildState waitUntilTransition() { std::unique_lock Lock(MBuildResultMutex); - MBuildCV.wait(Lock, [&] { - To = State; - return State != From; - }); - return To; + MBuildCV.wait(Lock, [&] { return State != BuildState::BS_InProgress; }); + return State.load(); } void updateAndNotify(BuildState DesiredState) { @@ -729,29 +724,31 @@ class KernelProgramCache { auto /* std::shared_ptr */ getOrBuild(GetCachedBuildFT &&GetCachedBuild, BuildFT &&Build, EvictFT &&EvictFunc = nullptr) { - using BuildState = KernelProgramCache::BuildState; constexpr size_t MaxAttempts = 2; for (size_t AttemptCounter = 0;; ++AttemptCounter) { auto /* std::pair, bool> */ Res = GetCachedBuild(); auto &BuildResult = Res.first; assert(BuildResult != nullptr); - BuildState Expected = BuildState::BS_Initial; - BuildState Desired = BuildState::BS_InProgress; - if (!BuildResult->State.compare_exchange_strong(Expected, Desired)) { + BuildState CurrentState = BuildState::BS_Initial; // initial is expected + if (!BuildResult->State.compare_exchange_strong( + CurrentState, BuildState::BS_InProgress)) { // no insertion took place, thus some other thread has already inserted // smth in the cache - BuildState NewState = BuildResult->waitUntilTransition(); + + if (CurrentState == BuildState::BS_InProgress) { + CurrentState = BuildResult->waitUntilTransition(); + } // Build succeeded. - if (NewState == BuildState::BS_Done) { + if (CurrentState == BuildState::BS_Done) { if constexpr (!std::is_same_v) EvictFunc(BuildResult->Val, /*IsBuilt=*/false); return BuildResult; } // Build failed, or this is the last attempt. - if (NewState == BuildState::BS_Failed || + if (CurrentState == BuildState::BS_Failed || AttemptCounter + 1 == MaxAttempts) { if (BuildResult->Error.isFilledIn()) throw detail::set_ur_error(