Skip to content

Commit e32e26e

Browse files
author
Hugh Delaney
committed
Multi dev ctx for hip adapter
1 parent f807b89 commit e32e26e

File tree

17 files changed

+971
-589
lines changed

17 files changed

+971
-589
lines changed

sycl/plugins/unified_runtime/ur/adapters/hip/context.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@
1616
UR_APIEXPORT ur_result_t UR_APICALL urContextCreate(
1717
uint32_t DeviceCount, const ur_device_handle_t *phDevices,
1818
const ur_context_properties_t *, ur_context_handle_t *phContext) {
19-
std::ignore = DeviceCount;
20-
assert(DeviceCount == 1);
2119
ur_result_t RetErr = UR_RESULT_SUCCESS;
2220

2321
std::unique_ptr<ur_context_handle_t_> ContextPtr{nullptr};
2422
try {
2523
// Create a scoped context.
2624
ContextPtr = std::unique_ptr<ur_context_handle_t_>(
27-
new ur_context_handle_t_{*phDevices});
25+
new ur_context_handle_t_{phDevices, DeviceCount});
2826

2927
static std::once_flag InitFlag;
3028
std::call_once(
@@ -56,7 +54,7 @@ urContextGetInfo(ur_context_handle_t hContext, ur_context_info_t propName,
5654
case UR_CONTEXT_INFO_NUM_DEVICES:
5755
return ReturnValue(1);
5856
case UR_CONTEXT_INFO_DEVICES:
59-
return ReturnValue(hContext->getDevice());
57+
return ReturnValue(hContext->getDevices());
6058
case UR_CONTEXT_INFO_REFERENCE_COUNT:
6159
return ReturnValue(hContext->getReferenceCount());
6260
case UR_CONTEXT_INFO_ATOMIC_MEMORY_ORDER_CAPABILITIES:
@@ -99,8 +97,10 @@ urContextRetain(ur_context_handle_t hContext) {
9997

10098
UR_APIEXPORT ur_result_t UR_APICALL urContextGetNativeHandle(
10199
ur_context_handle_t hContext, ur_native_handle_t *phNativeContext) {
100+
// FIXME this only returns the native context of the first device in the
101+
// SYCL context. This entry point should be deprecated.
102102
*phNativeContext = reinterpret_cast<ur_native_handle_t>(
103-
hContext->getDevice()->getNativeContext());
103+
hContext->getDevices()[0]->getNativeContext());
104104
return UR_RESULT_SUCCESS;
105105
}
106106

sycl/plugins/unified_runtime/ur/adapters/hip/context.hpp

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,24 @@ typedef void (*ur_context_extended_deleter_t)(void *UserData);
2828
/// with a given device and control access to said device from the user side.
2929
/// UR API context are objects that are passed to functions, and not bound
3030
/// to threads.
31-
/// The ur_context_handle_t_ object doesn't implement this behavior. It only
32-
/// holds the HIP context data. The RAII object \ref ScopedDevice implements
33-
/// the active context behavior.
3431
///
35-
/// <b> Primary vs UserDefined context </b>
32+
/// Since the ur_context_handle_t can contain multiple devices, and a `hipCtx_t`
33+
/// refers to only a single device, the `hipCtx_t` is more tightly coupled to a
34+
/// ur_device_handle_t than a ur_context_handle_t. In order to remove some
35+
/// ambiguities about the different semantics of ur_context_handle_t s and
36+
/// native `hipCtx_t`, we access the native `hipCtx_t` solely through the
37+
/// ur_device_handle_t class, by using the RAII object \ref ScopedDevice, which
38+
/// sets the active device (by setting the active native `hipCtx_t`).
3639
///
37-
/// HIP has two different types of context, the Primary context,
38-
/// which is usable by all threads on a given process for a given device, and
39-
/// the aforementioned custom contexts.
40-
/// The HIP documentation, and performance analysis, suggest using the Primary
41-
/// context whenever possible. The Primary context is also used by the HIP
42-
/// Runtime API. For UR applications to interop with HIP Runtime API, they have
43-
/// to use the primary context - and make that active in the thread. The
44-
/// `ur_context_handle_t_` object can be constructed with a `kind` parameter
45-
/// that allows to construct a Primary or `UserDefined` context, so that
46-
/// the UR object interface is always the same.
40+
/// <b> Primary vs User-defined `hipCtx_t` </b>
41+
///
42+
/// HIP has two different types of `hipCtx_t`, the Primary context, which is
43+
/// usable by all threads on a given process for a given device, and the
44+
/// aforementioned custom `hipCtx_t`s.
45+
/// The HIP documentation, confirmed with performance analysis, suggest using
46+
/// the Primary context whenever possible. The Primary context is also used by
47+
/// the HIP Runtime API. For UR applications to interop with HIP Runtime API,
48+
/// they have to use the primary context - and make that active in the thread.
4749
///
4850
/// <b> Destructor callback </b>
4951
///
@@ -53,6 +55,15 @@ typedef void (*ur_context_extended_deleter_t)(void *UserData);
5355
/// See proposal for details.
5456
/// https://github.com/codeplaysoftware/standards-proposals/blob/master/extended-context-destruction/index.md
5557
///
58+
/// <b> Memory Management for Devices in a Context <\b>
59+
///
60+
/// A ur_buffer_ is associated with a ur_context_handle_t_, which may refer to
61+
/// multiple devices. Therefore the ur_buffer_ must handle a native allocation
62+
/// for each device in the context. UR is responsible for automatically
63+
/// handling event dependencies for kernels writing to or reading from the
64+
/// same ur_buffer_ and migrating memory between native allocations for
65+
/// devices in the same ur_context_handle_t_ if necessary.
66+
///
5667
struct ur_context_handle_t_ {
5768

5869
struct deleter_data {
@@ -64,15 +75,23 @@ struct ur_context_handle_t_ {
6475

6576
using native_type = hipCtx_t;
6677

67-
ur_device_handle_t DeviceId;
78+
std::vector<ur_device_handle_t> Devices;
79+
uint32_t NumDevices;
80+
6881
std::atomic_uint32_t RefCount;
6982

70-
ur_context_handle_t_(ur_device_handle_t DevId)
71-
: DeviceId{DevId}, RefCount{1} {
72-
urDeviceRetain(DeviceId);
83+
ur_context_handle_t_(const ur_device_handle_t *Devs, uint32_t NumDevices)
84+
: Devices{Devs, Devs + NumDevices}, NumDevices{NumDevices}, RefCount{1} {
85+
for (auto &Dev : Devices) {
86+
urDeviceRetain(Dev);
87+
}
7388
};
7489

75-
~ur_context_handle_t_() { urDeviceRelease(DeviceId); }
90+
~ur_context_handle_t_() {
91+
for (auto &Dev : Devices) {
92+
urDeviceRelease(Dev);
93+
}
94+
}
7695

7796
void invokeExtendedDeleters() {
7897
std::lock_guard<std::mutex> Guard(Mutex);
@@ -87,7 +106,9 @@ struct ur_context_handle_t_ {
87106
ExtendedDeleters.emplace_back(deleter_data{Function, UserData});
88107
}
89108

90-
ur_device_handle_t getDevice() const noexcept { return DeviceId; }
109+
std::vector<ur_device_handle_t> getDevices() const noexcept {
110+
return Devices;
111+
}
91112

92113
uint32_t incrementReferenceCount() noexcept { return ++RefCount; }
93114

sycl/plugins/unified_runtime/ur/adapters/hip/device.hpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ struct ur_device_handle_t_ {
2323
std::atomic_uint32_t RefCount;
2424
ur_platform_handle_t Platform;
2525
hipCtx_t HIPContext;
26+
size_t DeviceIndex; // The index of the device in the UR context
2627

2728
public:
2829
ur_device_handle_t_(native_type HipDevice, hipCtx_t Context,
29-
ur_platform_handle_t Platform)
30+
ur_platform_handle_t Platform, size_t DeviceIndex)
3031
: HIPDevice(HipDevice), RefCount{1}, Platform(Platform),
31-
HIPContext(Context) {}
32+
HIPContext(Context), DeviceIndex(DeviceIndex) {}
3233

3334
~ur_device_handle_t_() {
3435
UR_CHECK_ERROR(hipDevicePrimaryCtxRelease(HIPDevice));
@@ -41,17 +42,25 @@ struct ur_device_handle_t_ {
4142
ur_platform_handle_t getPlatform() const noexcept { return Platform; };
4243

4344
hipCtx_t getNativeContext() { return HIPContext; };
45+
46+
// Returns the index of the device in question relative to the other devices
47+
// in the platform
48+
size_t getIndex() { return DeviceIndex; }
4449
};
4550

4651
int getAttribute(ur_device_handle_t Device, hipDeviceAttribute_t Attribute);
4752

4853
namespace {
49-
/// RAII type to guarantee recovering original HIP context
50-
/// Scoped context is used across all UR HIP plugin implementation
51-
/// to activate the UR Context on the current thread, matching the
54+
/// RAII type to guarantee recovering original HIP device. In UR the
55+
/// `ScopedDevice` sets the active device by using the native underlying
56+
/// `hipCtx_t`. Since a UR context can contain multiple devices, whereas a
57+
/// `hipCtx_t` refers to a single device, it is semantically clearer to access
58+
/// the `hipCtx_t` through the UR device rather than the UR context.
59+
/// Scoped device is used across all UR HIP plugin implementation
60+
/// to activate the UR Device on the current thread, matching the
5261
/// HIP driver semantics where the context used for the HIP Driver
5362
/// API is the one active on the thread.
54-
/// The implementation tries to avoid replacing the hipCtx_t if it cans
63+
/// The implementation tries to avoid replacing the hipCtx_t if it can
5564
class ScopedDevice {
5665
hipCtx_t Original;
5766
bool NeedToRecover;

0 commit comments

Comments
 (0)