Skip to content

Revert "[SYCL] Refactor program build and cache" #8192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sycl/source/detail/kernel_program_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace sycl {
__SYCL_INLINE_VER_NAMESPACE(_V1) {
namespace detail {
KernelProgramCache::~KernelProgramCache() {
for (auto &ProgIt : MCachedPrograms.Cache) {
for (auto &ProgIt : MCachedPrograms) {
ProgramWithBuildStateT &ProgWithState = ProgIt.second;
PiProgramT *ToBeDeleted = ProgWithState.Ptr.load();

Expand Down
68 changes: 6 additions & 62 deletions sycl/source/detail/kernel_program_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,13 @@ class KernelProgramCache {
bool isFilledIn() const { return !Msg.empty(); }
};

/// Denotes the state of a build.
enum BuildState { BS_InProgress, BS_Done, BS_Failed };

/// Denotes pointer to some entity with its general state and build error.
/// The pointer is not null if and only if the entity is usable.
/// State of the entity is provided by the user of cache instance.
/// Currently there is only a single user - ProgramManager class.
template <typename T> struct BuildResult {
std::atomic<T *> Ptr;
std::atomic<BuildState> State;
std::atomic<int> State;
BuildError Error;

/// Condition variable to signal that build result is ready.
Expand All @@ -65,23 +62,15 @@ class KernelProgramCache {
/// A mutex to be employed along with MBuildCV.
std::mutex MBuildResultMutex;

BuildResult(T *P, BuildState S) : Ptr{P}, State{S}, Error{"", 0} {}
BuildResult(T *P, int S) : Ptr{P}, State{S}, Error{"", 0} {}
};

using PiProgramT = std::remove_pointer<RT::PiProgram>::type;
using PiProgramPtrT = std::atomic<PiProgramT *>;
using ProgramWithBuildStateT = BuildResult<PiProgramT>;
using ProgramCacheKeyT = std::pair<std::pair<SerializedObj, std::uintptr_t>,
std::pair<RT::PiDevice, std::string>>;
using CommonProgramKeyT = std::pair<std::uintptr_t, RT::PiDevice>;

struct ProgramCache {
std::map<ProgramCacheKeyT, ProgramWithBuildStateT> Cache;
std::multimap<CommonProgramKeyT, ProgramCacheKeyT> KeyMap;

size_t size() const noexcept { return Cache.size(); }
};

using ProgramCacheT = std::map<ProgramCacheKeyT, ProgramWithBuildStateT>;
using ContextPtr = context_impl *;

using PiKernelT = std::remove_pointer<RT::PiKernel>::type;
Expand All @@ -102,66 +91,21 @@ class KernelProgramCache {

void setContextPtr(const ContextPtr &AContext) { MParentContext = AContext; }

Locked<ProgramCache> acquireCachedPrograms() {
Locked<ProgramCacheT> acquireCachedPrograms() {
return {MCachedPrograms, MProgramCacheMutex};
}

Locked<KernelCacheT> acquireKernelsPerProgramCache() {
return {MKernelsPerProgramCache, MKernelsPerProgramCacheMutex};
}

std::pair<ProgramWithBuildStateT *, bool>
getOrInsertProgram(const ProgramCacheKeyT &CacheKey) {
auto LockedCache = acquireCachedPrograms();
auto &ProgCache = LockedCache.get();
auto Inserted = ProgCache.Cache.emplace(
std::piecewise_construct, std::forward_as_tuple(CacheKey),
std::forward_as_tuple(nullptr, BS_InProgress));
if (Inserted.second) {
// Save reference between the common key and the full key.
CommonProgramKeyT CommonKey =
std::make_pair(CacheKey.first.second, CacheKey.second.first);
ProgCache.KeyMap.emplace(std::piecewise_construct,
std::forward_as_tuple(CommonKey),
std::forward_as_tuple(CacheKey));
}
return std::make_pair(&Inserted.first->second, Inserted.second);
}

std::pair<KernelWithBuildStateT *, bool>
getOrInsertKernel(RT::PiProgram Program, const std::string &KernelName) {
auto LockedCache = acquireKernelsPerProgramCache();
auto &Cache = LockedCache.get()[Program];
auto Inserted = Cache.emplace(
std::piecewise_construct, std::forward_as_tuple(KernelName),
std::forward_as_tuple(nullptr, BS_InProgress));
return std::make_pair(&Inserted.first->second, Inserted.second);
}

template <typename T, class Predicate>
void waitUntilBuilt(BuildResult<T> &BR, Predicate Pred) const {
std::unique_lock<std::mutex> Lock(BR.MBuildResultMutex);

BR.MBuildCV.wait(Lock, Pred);
}

template <typename ExceptionT, typename RetT>
RetT *waitUntilBuilt(BuildResult<RetT> *BuildResult) {
// Any thread which will find nullptr in cache will wait until the pointer
// is not null anymore.
waitUntilBuilt(*BuildResult, [BuildResult]() {
int State = BuildResult->State.load();
return State == BuildState::BS_Done || State == BuildState::BS_Failed;
});

if (BuildResult->Error.isFilledIn()) {
const BuildError &Error = BuildResult->Error;
throw ExceptionT(Error.Msg, Error.Code);
}

return BuildResult->Ptr.load();
}

template <typename T> void notifyAllBuild(BuildResult<T> &BR) const {
BR.MBuildCV.notify_all();
}
Expand All @@ -188,7 +132,7 @@ class KernelProgramCache {
///
/// This member function should only be used in unit tests.
void reset() {
MCachedPrograms = ProgramCache{};
MCachedPrograms = ProgramCacheT{};
MKernelsPerProgramCache = KernelCacheT{};
MKernelFastCache = KernelFastCacheT{};
}
Expand All @@ -197,7 +141,7 @@ class KernelProgramCache {
std::mutex MProgramCacheMutex;
std::mutex MKernelsPerProgramCacheMutex;

ProgramCache MCachedPrograms;
ProgramCacheT MCachedPrograms;
KernelCacheT MKernelsPerProgramCache;
ContextPtr MParentContext;

Expand Down
Loading