Skip to content

Commit

Permalink
[SYCL] Introduce per-field lock in global handler (#4042)
Browse files Browse the repository at this point in the history
Signed-off-by: Sergey Kanaev <sergey.kanaev@intel.com>
  • Loading branch information
sergei authored Jul 7, 2021
1 parent c69a311 commit 7fc8aa0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 86 deletions.
100 changes: 25 additions & 75 deletions sycl/source/detail/global_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
__SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {
using LockGuard = std::lock_guard<SpinLock>;

GlobalHandler::GlobalHandler() = default;
GlobalHandler::~GlobalHandler() = default;

Expand All @@ -32,109 +34,57 @@ GlobalHandler &GlobalHandler::instance() {
return *SyclGlobalObjectsHandler;
}

Scheduler &GlobalHandler::getScheduler() {
if (MScheduler)
return *MScheduler;
template <typename T, typename... Types>
T &GlobalHandler::getOrCreate(InstWithLock<T> &IWL, Types... Args) {
const LockGuard Lock{IWL.Lock};

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MScheduler)
MScheduler = std::make_unique<Scheduler>();
if (!IWL.Inst)
IWL.Inst = std::make_unique<T>(Args...);

return *MScheduler;
return *IWL.Inst;
}
ProgramManager &GlobalHandler::getProgramManager() {
if (MProgramManager)
return *MProgramManager;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MProgramManager)
MProgramManager = std::make_unique<ProgramManager>();
Scheduler &GlobalHandler::getScheduler() { return getOrCreate(MScheduler); }

return *MProgramManager;
ProgramManager &GlobalHandler::getProgramManager() {
return getOrCreate(MProgramManager);
}
Sync &GlobalHandler::getSync() {
if (MSync)
return *MSync;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MSync)
MSync = std::make_unique<Sync>();
Sync &GlobalHandler::getSync() { return getOrCreate(MSync); }

return *MSync;
}
std::vector<PlatformImplPtr> &GlobalHandler::getPlatformCache() {
if (MPlatformCache)
return *MPlatformCache;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MPlatformCache)
MPlatformCache = std::make_unique<std::vector<PlatformImplPtr>>();

return *MPlatformCache;
return getOrCreate(MPlatformCache);
}
std::mutex &GlobalHandler::getPlatformMapMutex() {
if (MPlatformMapMutex)
return *MPlatformMapMutex;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MPlatformMapMutex)
MPlatformMapMutex = std::make_unique<std::mutex>();

return *MPlatformMapMutex;
std::mutex &GlobalHandler::getPlatformMapMutex() {
return getOrCreate(MPlatformMapMutex);
}
std::mutex &GlobalHandler::getFilterMutex() {
if (MFilterMutex)
return *MFilterMutex;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MFilterMutex)
MFilterMutex = std::make_unique<std::mutex>();

return *MFilterMutex;
std::mutex &GlobalHandler::getFilterMutex() {
return getOrCreate(MFilterMutex);
}
std::vector<plugin> &GlobalHandler::getPlugins() {
if (MPlugins)
return *MPlugins;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MPlugins)
MPlugins = std::make_unique<std::vector<plugin>>();

return *MPlugins;
return getOrCreate(MPlugins);
}
device_filter_list &
GlobalHandler::getDeviceFilterList(const std::string &InitValue) {
if (MDeviceFilterList)
return *MDeviceFilterList;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MDeviceFilterList)
MDeviceFilterList = std::make_unique<device_filter_list>(InitValue);

return *MDeviceFilterList;
return getOrCreate(MDeviceFilterList, InitValue);
}

std::mutex &GlobalHandler::getHandlerExtendedMembersMutex() {
if (MHandlerExtendedMembersMutex)
return *MHandlerExtendedMembersMutex;

const std::lock_guard<SpinLock> Lock{MFieldsLock};
if (!MHandlerExtendedMembersMutex)
MHandlerExtendedMembersMutex = std::make_unique<std::mutex>();

return *MHandlerExtendedMembersMutex;
return getOrCreate(MHandlerExtendedMembersMutex);
}

void shutdown() {
// First, release resources, that may access plugins.
GlobalHandler::instance().MScheduler.reset(nullptr);
GlobalHandler::instance().MProgramManager.reset(nullptr);
GlobalHandler::instance().MPlatformCache.reset(nullptr);
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);

// Call to GlobalHandler::instance().getPlugins() initializes plugins. If
// user application has loaded SYCL runtime, and never called any APIs,
// there's no need to load and unload plugins.
if (GlobalHandler::instance().MPlugins) {
if (GlobalHandler::instance().MPlugins.Inst) {
for (plugin &Plugin : GlobalHandler::instance().getPlugins()) {
// PluginParameter is reserved for future use that can control
// some parameters in the plugin tear-down process.
Expand All @@ -143,7 +93,7 @@ void shutdown() {
Plugin.call_nocheck<PiApiKind::piTearDown>(PluginParameter);
Plugin.unload();
}
GlobalHandler::instance().MPlugins.reset(nullptr);
GlobalHandler::instance().MPlugins.Inst.reset(nullptr);
}

// Release the rest of global resources.
Expand Down
27 changes: 16 additions & 11 deletions sycl/source/detail/global_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,24 @@ class GlobalHandler {
GlobalHandler();
~GlobalHandler();

SpinLock MFieldsLock;
template <typename T> struct InstWithLock {
std::unique_ptr<T> Inst;
SpinLock Lock;
};

// Do not forget to update shutdown() function if needed.
std::unique_ptr<Scheduler> MScheduler;
std::unique_ptr<ProgramManager> MProgramManager;
std::unique_ptr<Sync> MSync;
std::unique_ptr<std::vector<PlatformImplPtr>> MPlatformCache;
std::unique_ptr<std::mutex> MPlatformMapMutex;
std::unique_ptr<std::mutex> MFilterMutex;
std::unique_ptr<std::vector<plugin>> MPlugins;
std::unique_ptr<device_filter_list> MDeviceFilterList;
template <typename T, typename... Types>
T &getOrCreate(InstWithLock<T> &IWL, Types... Args);

InstWithLock<Scheduler> MScheduler;
InstWithLock<ProgramManager> MProgramManager;
InstWithLock<Sync> MSync;
InstWithLock<std::vector<PlatformImplPtr>> MPlatformCache;
InstWithLock<std::mutex> MPlatformMapMutex;
InstWithLock<std::mutex> MFilterMutex;
InstWithLock<std::vector<plugin>> MPlugins;
InstWithLock<device_filter_list> MDeviceFilterList;
// The mutex for synchronizing accesses to handlers extended members
std::unique_ptr<std::mutex> MHandlerExtendedMembersMutex;
InstWithLock<std::mutex> MHandlerExtendedMembersMutex;
};
} // namespace detail
} // namespace sycl
Expand Down

0 comments on commit 7fc8aa0

Please sign in to comment.