Skip to content

Commit 315593d

Browse files
authored
[SYCL] Add support for default contexts (#2805)
A default context is now defined per platform. The default context initially contains all devices in the platform. Queue creation will use the device's platform's default context instead of creating a new context with that device. The new extension introduces ext_oneapi_get_default_context() member function to the platform class. DPC++ runtime allows control of this feature with SYCL_ENABLE_DEFAULT_CONTEXTS env variable. It is enabled by default on Linux and disabled on Windows.
1 parent 23ca0c2 commit 315593d

21 files changed

+300
-14
lines changed

sycl/doc/EnvironmentVariables.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ subject to change. Do not rely on these variables in production code.
4747
| `SYCL_CACHE_THRESHOLD` | Positive integer | Cache eviction threshold in days (default value is 7 for 1 week). Set to 0 for disabling time-based cache eviction. |
4848
| `SYCL_CACHE_MIN_DEVICE_IMAGE_SIZE` | Positive integer | Minimum size of device code image in bytes which is reasonable to cache on disk because disk access operation may take more time than do JIT compilation for it. Default value is 0 to cache all images. |
4949
| `SYCL_CACHE_MAX_DEVICE_IMAGE_SIZE` | Positive integer | Maximum size of device image in bytes which is cached. Too big kernels may overload disk too fast. Default value is 1 GB. |
50+
| `SYCL_ENABLE_DEFAULT_CONTEXTS` | '1' or '0' | Enable ('1') or disable ('0') creation of default platform contexts in SYCL runtime. The default context for each platform contains all devices in the platform. Refer to [Platform Default Contexts](extensions/PlatformContext/PlatformContext.adoc) extension to learn more. Enabled by default on Linux and disabled on Windows. |
5051

5152
`(*) Note: Any means this environment variable is effective when set to any non-null value.`
5253

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
= SYCL(TM) Proposals: Platform Default Contexts
2+
James Brodman <james[email protected]>
3+
v0.1
4+
:source-highlighter: pygments
5+
:icons: font
6+
:y: icon:check[role="green"]
7+
:n: icon:times[role="red"]
8+
9+
== Platform Default Contexts
10+
11+
This extension adds the notion of a default SYCL context per SYCL platform. The default context for each platform contains all devices in the platform.
12+
13+
The platform class gains one new method:
14+
15+
[cols="^60a,40"]
16+
|===
17+
| Member Function | Description
18+
19+
|
20+
[source,c++]
21+
----
22+
context ext_oneapi_get_default_context()
23+
----
24+
25+
| Returns the current default context for this `platform`
26+
27+
|===
28+
29+
This extension also modifies the behavior of `queue` constructors. Queues will no longer create a new `context` upon construction. Instead, they will use the default context from the device's platform.
30+
31+
== Feature Test Macro
32+
33+
This extension defines the macro `SYCL_EXT_ONEAPI_DEFAULT_CONTEXT` to `1` to indicate that it is enabled.
34+

sycl/doc/extensions/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ DPC++ extensions status:
3737
| [Use Pinned Memory Property](UsePinnedMemoryProperty/UsePinnedMemoryPropery.adoc) | Supported | |
3838
| [Level-Zero backend specification](LevelZeroBackend/LevelZeroBackend.md) | Supported | |
3939
| [ITT annotations support](ITTAnnotations/ITTAnnotations.rst) | Supported | |
40+
| [Platform Context](PlatformContext/PlatformContext.adoc) | Proposal | |
4041
| [SYCL_EXT_ONEAPI_DEVICE_IF](DeviceIf/device_if.asciidoc) | Proposal | |
4142
| [SYCL_INTEL_group_sort](GroupAlgorithms/SYCL_INTEL_group_sort.asciidoc) | Proposal | |
4243
| [Invoke SIMD](InvokeSIMD/InvokeSIMD.asciidoc) | Proposal | |

sycl/include/CL/sycl/platform.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#pragma once
10+
1011
#include <CL/sycl/aspects.hpp>
12+
#include <CL/sycl/context.hpp>
1113
#include <CL/sycl/detail/common.hpp>
1214
#include <CL/sycl/detail/export.hpp>
1315
#include <CL/sycl/stl.hpp>
@@ -25,6 +27,9 @@ namespace detail {
2527
class platform_impl;
2628
}
2729

30+
// Feature test macro for Default Context
31+
#define SYCL_EXT_ONEAPI_DEFAULT_CONTEXT 1
32+
2833
/// Encapsulates a SYCL platform on which kernels may be executed.
2934
///
3035
/// \ingroup sycl_api
@@ -132,6 +137,11 @@ class __SYCL_EXPORT platform {
132137
/// given feature.
133138
bool has(aspect Aspect) const;
134139

140+
/// Return this platform's default context
141+
///
142+
/// \return the default context
143+
context ext_oneapi_get_default_context() const;
144+
135145
private:
136146
pi_native_handle getNative() const;
137147

sycl/plugins/cuda/pi_cuda.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pi_result forLatestEvents(const pi_event *event_wait_list,
111111
///
112112
pi_result check_error(CUresult result, const char *function, int line,
113113
const char *file) {
114-
if (result == CUDA_SUCCESS) {
114+
if (result == CUDA_SUCCESS || result == CUDA_ERROR_DEINITIALIZED) {
115115
return PI_SUCCESS;
116116
}
117117

sycl/source/detail/config.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ CONFIG(SYCL_OVERRIDE_PI_OPENCL, 1024, __SYCL_OVERRIDE_PI_OPENCL)
3838
CONFIG(SYCL_OVERRIDE_PI_LEVEL_ZERO, 1024, __SYCL_OVERRIDE_PI_LEVEL_ZERO)
3939
CONFIG(SYCL_OVERRIDE_PI_CUDA, 1024, __SYCL_OVERRIDE_PI_CUDA)
4040
CONFIG(SYCL_OVERRIDE_PI_ROCM, 1024, __SYCL_OVERRIDE_PI_ROCM)
41+
CONFIG(SYCL_ENABLE_DEFAULT_CONTEXTS, 1, __SYCL_ENABLE_DEFAULT_CONTEXTS)

sycl/source/detail/config.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,38 @@ template <> class SYCLConfig<SYCL_DEVICE_FILTER> {
285285
}
286286
};
287287

288+
template <> class SYCLConfig<SYCL_ENABLE_DEFAULT_CONTEXTS> {
289+
using BaseT = SYCLConfigBase<SYCL_ENABLE_DEFAULT_CONTEXTS>;
290+
291+
public:
292+
static bool get() {
293+
#ifdef WIN32
294+
constexpr bool DefaultValue = false;
295+
#else
296+
constexpr bool DefaultValue = true;
297+
#endif
298+
299+
const char *ValStr = getCachedValue();
300+
301+
if (!ValStr)
302+
return DefaultValue;
303+
304+
return ValStr[0] == '1';
305+
}
306+
307+
static void reset() { (void)getCachedValue(/*ResetCache=*/true); }
308+
309+
static const char *getName() { return BaseT::MConfigName; }
310+
311+
private:
312+
static const char *getCachedValue(bool ResetCache = false) {
313+
static const char *ValStr = BaseT::getRawValue();
314+
if (ResetCache)
315+
ValStr = BaseT::getRawValue();
316+
return ValStr;
317+
}
318+
};
319+
288320
} // namespace detail
289321
} // namespace sycl
290322
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/global_handler.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ ProgramManager &GlobalHandler::getProgramManager() {
5151
return getOrCreate(MProgramManager);
5252
}
5353

54+
std::unordered_map<PlatformImplPtr, ContextImplPtr> &
55+
GlobalHandler::getPlatformToDefaultContextCache() {
56+
return getOrCreate(MPlatformToDefaultContextCache);
57+
}
58+
59+
std::mutex &GlobalHandler::getPlatformToDefaultContextCacheMutex() {
60+
return getOrCreate(MPlatformToDefaultContextCacheMutex);
61+
}
62+
5463
Sync &GlobalHandler::getSync() { return getOrCreate(MSync); }
5564

5665
std::vector<PlatformImplPtr> &GlobalHandler::getPlatformCache() {
@@ -84,6 +93,16 @@ void shutdown() {
8493
// First, release resources, that may access plugins.
8594
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
8695
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);
96+
#ifndef _WIN32
97+
GlobalHandler::instance().MPlatformToDefaultContextCache.Inst.reset(nullptr);
98+
#else
99+
// Windows does not maintain dependencies between dynamically loaded libraries
100+
// and can unload SYCL runtime dependencies before sycl.dll's DllMain has
101+
// finished. To avoid calls to nowhere, intentionally leak platform to device
102+
// cache. This will prevent destructors from being called, thus no PI cleanup
103+
// routines will be called in the end.
104+
GlobalHandler::instance().MPlatformToDefaultContextCache.Inst.release();
105+
#endif
87106
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);
88107

89108
// Call to GlobalHandler::instance().getPlugins() initializes plugins. If

sycl/source/detail/global_handler.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
#include <CL/sycl/detail/util.hpp>
1313

1414
#include <memory>
15+
#include <unordered_map>
1516

1617
__SYCL_INLINE_NAMESPACE(cl) {
1718
namespace sycl {
1819
namespace detail {
1920
class platform_impl;
21+
class context_impl;
2022
class Scheduler;
2123
class ProgramManager;
2224
class Sync;
@@ -25,6 +27,7 @@ class device_filter_list;
2527
class XPTIRegistry;
2628

2729
using PlatformImplPtr = std::shared_ptr<platform_impl>;
30+
using ContextImplPtr = std::shared_ptr<context_impl>;
2831

2932
/// Wrapper class for global data structures with non-trivial destructors.
3033
///
@@ -53,6 +56,11 @@ class GlobalHandler {
5356
ProgramManager &getProgramManager();
5457
Sync &getSync();
5558
std::vector<PlatformImplPtr> &getPlatformCache();
59+
60+
std::unordered_map<PlatformImplPtr, ContextImplPtr> &
61+
getPlatformToDefaultContextCache();
62+
63+
std::mutex &getPlatformToDefaultContextCacheMutex();
5664
std::mutex &getPlatformMapMutex();
5765
std::mutex &getFilterMutex();
5866
std::vector<plugin> &getPlugins();
@@ -80,6 +88,9 @@ class GlobalHandler {
8088
InstWithLock<ProgramManager> MProgramManager;
8189
InstWithLock<Sync> MSync;
8290
InstWithLock<std::vector<PlatformImplPtr>> MPlatformCache;
91+
InstWithLock<std::unordered_map<PlatformImplPtr, ContextImplPtr>>
92+
MPlatformToDefaultContextCache;
93+
InstWithLock<std::mutex> MPlatformToDefaultContextCacheMutex;
8394
InstWithLock<std::mutex> MPlatformMapMutex;
8495
InstWithLock<std::mutex> MFilterMutex;
8596
InstWithLock<std::vector<plugin>> MPlugins;

sycl/source/detail/platform_impl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <algorithm>
1919
#include <cstring>
20+
#include <mutex>
2021
#include <string>
2122
#include <vector>
2223

sycl/source/detail/platform_impl.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#pragma once
10+
1011
#include <CL/sycl/detail/common.hpp>
1112
#include <CL/sycl/detail/pi.hpp>
1213
#include <CL/sycl/info/info_desc.hpp>

sycl/source/detail/queue_impl.hpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <CL/sycl/properties/queue_properties.hpp>
2121
#include <CL/sycl/property_list.hpp>
2222
#include <CL/sycl/stl.hpp>
23+
#include <detail/config.hpp>
2324
#include <detail/context_impl.hpp>
2425
#include <detail/device_impl.hpp>
2526
#include <detail/event_impl.hpp>
@@ -50,6 +51,22 @@ enum QueueOrder { Ordered, OOO };
5051

5152
class queue_impl {
5253
public:
54+
// \return a default context for the platform if it includes the device
55+
// passed and default contexts are enabled, a new context otherwise.
56+
static ContextImplPtr getDefaultOrNew(const DeviceImplPtr &Device) {
57+
if (!SYCLConfig<SYCL_ENABLE_DEFAULT_CONTEXTS>::get())
58+
return detail::getSyclObjImpl(
59+
context{createSyclObjFromImpl<device>(Device), {}, {}});
60+
61+
ContextImplPtr DefaultContext = detail::getSyclObjImpl(
62+
Device->get_platform().ext_oneapi_get_default_context());
63+
64+
if (DefaultContext->hasDevice(Device))
65+
return DefaultContext;
66+
67+
return detail::getSyclObjImpl(
68+
context{createSyclObjFromImpl<device>(Device), {}, {}});
69+
}
5370
/// Constructs a SYCL queue from a device using an async_handler and
5471
/// property_list provided.
5572
///
@@ -59,14 +76,7 @@ class queue_impl {
5976
/// \param PropList is a list of properties to use for queue construction.
6077
queue_impl(const DeviceImplPtr &Device, const async_handler &AsyncHandler,
6178
const property_list &PropList)
62-
: queue_impl(Device,
63-
detail::getSyclObjImpl(
64-
context(createSyclObjFromImpl<device>(Device), {},
65-
(DefaultContextType == CUDAContextT::primary)
66-
? property_list{property::context::cuda::
67-
use_primary_context()}
68-
: property_list{})),
69-
AsyncHandler, PropList){};
79+
: queue_impl(Device, getDefaultOrNew(Device), AsyncHandler, PropList){};
7080

7181
/// Constructs a SYCL queue with an async_handler and property_list provided
7282
/// form a device and a context.

sycl/source/detail/scheduler/scheduler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,10 @@ void Scheduler::deallocateStreamBuffers(stream_impl *Impl) {
420420

421421
Scheduler::Scheduler() {
422422
sycl::device HostDevice;
423+
sycl::context HostContext{HostDevice};
423424
DefaultHostQueue = QueueImplPtr(
424-
new queue_impl(detail::getSyclObjImpl(HostDevice), /*AsyncHandler=*/{},
425+
new queue_impl(detail::getSyclObjImpl(HostDevice),
426+
detail::getSyclObjImpl(HostContext), /*AsyncHandler=*/{},
425427
/*PropList=*/{}));
426428
}
427429

sycl/source/platform.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#include <CL/sycl/info/info_desc.hpp>
1212
#include <CL/sycl/platform.hpp>
1313
#include <detail/backend_impl.hpp>
14+
#include <detail/config.hpp>
1415
#include <detail/force_device.hpp>
16+
#include <detail/global_handler.hpp>
1517
#include <detail/platform_impl.hpp>
1618

1719
__SYCL_INLINE_NAMESPACE(cl) {
@@ -65,5 +67,26 @@ bool platform::has(aspect Aspect) const { return impl->has(Aspect); }
6567

6668
#undef __SYCL_PARAM_TRAITS_SPEC
6769

70+
context platform::ext_oneapi_get_default_context() const {
71+
if (!detail::SYCLConfig<detail::SYCL_ENABLE_DEFAULT_CONTEXTS>::get())
72+
throw std::runtime_error("SYCL default contexts are not enabled");
73+
74+
// Keeping the default context for platforms in the global cache to avoid
75+
// shared_ptr based circular dependency between platform and context classes
76+
std::unordered_map<detail::PlatformImplPtr, detail::ContextImplPtr>
77+
&PlatformToDefaultContextCache =
78+
detail::GlobalHandler::instance().getPlatformToDefaultContextCache();
79+
80+
std::lock_guard Lock{detail::GlobalHandler::instance()
81+
.getPlatformToDefaultContextCacheMutex()};
82+
83+
auto It = PlatformToDefaultContextCache.find(impl);
84+
if (PlatformToDefaultContextCache.end() == It)
85+
std::tie(It, std::ignore) = PlatformToDefaultContextCache.insert(
86+
{impl, detail::getSyclObjImpl(context{get_devices()})});
87+
88+
return detail::createSyclObjFromImpl<context>(It->second);
89+
}
90+
6891
} // namespace sycl
6992
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/test/abi/sycl_symbols_linux.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4336,6 +4336,7 @@ _ZNK2cl4sycl7samplerneERKS1_
43364336
_ZNK2cl4sycl8platform11get_backendEv
43374337
_ZNK2cl4sycl8platform11get_devicesENS0_4info11device_typeE
43384338
_ZNK2cl4sycl8platform13has_extensionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
4339+
_ZNK2cl4sycl8platform30ext_oneapi_get_default_contextEv
43394340
_ZNK2cl4sycl8platform3getEv
43404341
_ZNK2cl4sycl8platform3hasENS0_6aspectE
43414342
_ZNK2cl4sycl8platform7is_hostEv

sycl/test/abi/sycl_symbols_windows.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,7 @@
17471747
?extractArgsAndReqs@handler@sycl@cl@@AEAAXXZ
17481748
?extractArgsAndReqsFromLambda@handler@sycl@cl@@AEAAXPEAD_KPEBUkernel_param_desc_t@detail@23@@Z
17491749
?extractArgsAndReqsFromLambda@handler@sycl@cl@@AEAAXPEAD_KPEBUkernel_param_desc_t@detail@23@_N@Z
1750+
?ext_oneapi_get_default_context@platform@sycl@cl@@QEBA?AVcontext@23@XZ
17501751
?fabs@__host_std@cl@@YA?AV?$vec@M$00@sycl@2@V342@@Z
17511752
?fabs@__host_std@cl@@YA?AV?$vec@M$01@sycl@2@V342@@Z
17521753
?fabs@__host_std@cl@@YA?AV?$vec@M$02@sycl@2@V342@@Z

sycl/unittests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ add_subdirectory(SYCL2020)
2222
add_subdirectory(thread_safety)
2323
add_subdirectory(program_manager)
2424
add_subdirectory(assert)
25+
add_subdirectory(Extensions)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
set(CMAKE_CXX_EXTENSIONS OFF)
2+
3+
# Enable exception handling for these unit tests
4+
set(LLVM_REQUIRES_EH 1)
5+
add_sycl_unittest(ExtensionsTests OBJECT
6+
DefaultContext.cpp
7+
)
8+

0 commit comments

Comments
 (0)