Skip to content

Commit b76d907

Browse files
authored
Merge pull request #1192 from maarquitos14/maronas/ext_composite_device
Initial support for sycl_ext_oneapi_composite_device
2 parents 3a1c48c + 5d322ee commit b76d907

File tree

11 files changed

+187
-2
lines changed

11 files changed

+187
-2
lines changed

include/ur_api.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,10 @@ typedef enum ur_device_info_t {
15301530
///< version than older devices.
15311531
UR_DEVICE_INFO_VIRTUAL_MEMORY_SUPPORT = 114, ///< [::ur_bool_t] return true if the device supports virtual memory.
15321532
UR_DEVICE_INFO_ESIMD_SUPPORT = 115, ///< [::ur_bool_t] return true if the device supports ESIMD.
1533+
UR_DEVICE_INFO_COMPONENT_DEVICES = 116, ///< [::ur_device_handle_t[]] The set of component devices contained by
1534+
///< this composite device.
1535+
UR_DEVICE_INFO_COMPOSITE_DEVICE = 117, ///< [::ur_device_handle_t] The composite device containing this component
1536+
///< device.
15331537
UR_DEVICE_INFO_BINDLESS_IMAGES_SUPPORT_EXP = 0x2000, ///< [::ur_bool_t] returns true if the device supports the creation of
15341538
///< bindless images
15351539
UR_DEVICE_INFO_BINDLESS_IMAGES_SHARED_USM_SUPPORT_EXP = 0x2001, ///< [::ur_bool_t] returns true if the device supports the creation of

include/ur_print.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2401,6 +2401,12 @@ inline std::ostream &operator<<(std::ostream &os, ur_device_info_t value) {
24012401
case UR_DEVICE_INFO_ESIMD_SUPPORT:
24022402
os << "UR_DEVICE_INFO_ESIMD_SUPPORT";
24032403
break;
2404+
case UR_DEVICE_INFO_COMPONENT_DEVICES:
2405+
os << "UR_DEVICE_INFO_COMPONENT_DEVICES";
2406+
break;
2407+
case UR_DEVICE_INFO_COMPOSITE_DEVICE:
2408+
os << "UR_DEVICE_INFO_COMPOSITE_DEVICE";
2409+
break;
24042410
case UR_DEVICE_INFO_BINDLESS_IMAGES_SUPPORT_EXP:
24052411
os << "UR_DEVICE_INFO_BINDLESS_IMAGES_SUPPORT_EXP";
24062412
break;
@@ -3809,6 +3815,34 @@ inline ur_result_t printTagged(std::ostream &os, const void *ptr, ur_device_info
38093815

38103816
os << ")";
38113817
} break;
3818+
case UR_DEVICE_INFO_COMPONENT_DEVICES: {
3819+
3820+
const ur_device_handle_t *tptr = (const ur_device_handle_t *)ptr;
3821+
os << "{";
3822+
size_t nelems = size / sizeof(ur_device_handle_t);
3823+
for (size_t i = 0; i < nelems; ++i) {
3824+
if (i != 0) {
3825+
os << ", ";
3826+
}
3827+
3828+
ur::details::printPtr(os,
3829+
tptr[i]);
3830+
}
3831+
os << "}";
3832+
} break;
3833+
case UR_DEVICE_INFO_COMPOSITE_DEVICE: {
3834+
const ur_device_handle_t *tptr = (const ur_device_handle_t *)ptr;
3835+
if (sizeof(ur_device_handle_t) > size) {
3836+
os << "invalid size (is: " << size << ", expected: >=" << sizeof(ur_device_handle_t) << ")";
3837+
return UR_RESULT_ERROR_INVALID_SIZE;
3838+
}
3839+
os << (const void *)(tptr) << " (";
3840+
3841+
ur::details::printPtr(os,
3842+
*tptr);
3843+
3844+
os << ")";
3845+
} break;
38123846
case UR_DEVICE_INFO_BINDLESS_IMAGES_SUPPORT_EXP: {
38133847
const ur_bool_t *tptr = (const ur_bool_t *)ptr;
38143848
if (sizeof(ur_bool_t) > size) {

scripts/core/device.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ etors:
396396
desc: "[$x_bool_t] return true if the device supports virtual memory."
397397
- name: ESIMD_SUPPORT
398398
desc: "[$x_bool_t] return true if the device supports ESIMD."
399+
- name: COMPONENT_DEVICES
400+
desc: "[$x_device_handle_t[]] The set of component devices contained by this composite device."
401+
- name: COMPOSITE_DEVICE
402+
desc: "[$x_device_handle_t] The composite device containing this component device."
399403
--- #--------------------------------------------------------------------------
400404
type: function
401405
desc: "Retrieves various information about device"

source/adapters/cuda/device.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice,
10221022
return ReturnValue(true);
10231023
case UR_DEVICE_INFO_ESIMD_SUPPORT:
10241024
return ReturnValue(false);
1025+
case UR_DEVICE_INFO_COMPONENT_DEVICES:
1026+
case UR_DEVICE_INFO_COMPOSITE_DEVICE:
1027+
// These two are exclusive of L0.
1028+
return ReturnValue(0);
10251029
case UR_DEVICE_INFO_MAX_READ_WRITE_IMAGE_ARGS:
10261030
case UR_DEVICE_INFO_GPU_EU_COUNT:
10271031
case UR_DEVICE_INFO_GPU_EU_SIMD_WIDTH:

source/adapters/hip/device.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice,
823823
return ReturnValue(false);
824824
case UR_DEVICE_INFO_ESIMD_SUPPORT:
825825
return ReturnValue(false);
826+
case UR_DEVICE_INFO_COMPONENT_DEVICES:
827+
case UR_DEVICE_INFO_COMPOSITE_DEVICE:
828+
// These two are exclusive of L0.
829+
return ReturnValue(0);
826830

827831
// TODO: Investigate if this information is available on HIP.
828832
case UR_DEVICE_INFO_GPU_EU_COUNT:

source/adapters/level_zero/device.cpp

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,34 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGet(
4242
// Filter available devices based on input DeviceType.
4343
std::vector<ur_device_handle_t> MatchedDevices;
4444
std::shared_lock<ur_shared_mutex> Lock(Platform->URDevicesCacheMutex);
45+
// We need to filter out composite devices when
46+
// ZE_FLAT_DEVICE_HIERARCHY=COMBINED. We can know if we are in combined
47+
// mode depending on the return value of zeDeviceGetRootDevice:
48+
// - If COMPOSITE, L0 returns cards as devices. Since we filter out
49+
// subdevices early, zeDeviceGetRootDevice must return nullptr, because we
50+
// only query for root-devices and they don't have any device higher up in
51+
// the hierarchy.
52+
// - If FLAT, according to L0 spec, zeDeviceGetRootDevice always returns
53+
// nullptr in this mode.
54+
// - If COMBINED, L0 returns tiles as devices, and zeDeviceGetRootdevice
55+
// returns the card containing a given tile.
56+
bool isCombinedMode =
57+
std::any_of(Platform->URDevicesCache.begin(),
58+
Platform->URDevicesCache.end(), [](const auto &D) {
59+
if (D->isSubDevice())
60+
return false;
61+
ze_device_handle_t RootDev = nullptr;
62+
// Query Root Device for root-devices.
63+
// We cannot use ZE2UR_CALL because under some circumstances
64+
// this call may return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE,
65+
// and ZE2UR_CALL will abort because it's not
66+
// UR_RESULT_SUCCESS. Instead, we use ZE_CALL_NOCHECK and we
67+
// check manually that the result is either
68+
// ZE_RESULT_SUCCESS or ZE_RESULT_ERROR_UNSUPPORTED_FEATURE.
69+
auto errc = ZE_CALL_NOCHECK(zeDeviceGetRootDevice,
70+
(D->ZeDevice, &RootDev));
71+
return (errc == ZE_RESULT_SUCCESS && RootDev != nullptr);
72+
});
4573
for (auto &D : Platform->URDevicesCache) {
4674
// Only ever return root-devices from urDeviceGet, but the
4775
// devices cache also keeps sub-devices.
@@ -71,8 +99,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGet(
7199
urPrint("Unknown device type");
72100
break;
73101
}
74-
if (Matched)
75-
MatchedDevices.push_back(D.get());
102+
103+
if (Matched) {
104+
bool isComposite =
105+
isCombinedMode && (D->ZeDeviceProperties->flags &
106+
ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE) == 0;
107+
if (!isComposite)
108+
MatchedDevices.push_back(D.get());
109+
}
76110
}
77111

78112
uint32_t ZeDeviceCount = MatchedDevices.size();
@@ -826,6 +860,62 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(
826860
return ReturnValue(result);
827861
}
828862

863+
case UR_DEVICE_INFO_COMPONENT_DEVICES: {
864+
ze_device_handle_t DevHandle = Device->ZeDevice;
865+
uint32_t SubDeviceCount = 0;
866+
// First call to get SubDeviceCount.
867+
ZE2UR_CALL(zeDeviceGetSubDevices, (DevHandle, &SubDeviceCount, nullptr));
868+
if (SubDeviceCount == 0)
869+
return ReturnValue(0);
870+
871+
std::vector<ze_device_handle_t> SubDevs(SubDeviceCount);
872+
// Second call to get the actual list of devices.
873+
ZE2UR_CALL(zeDeviceGetSubDevices,
874+
(DevHandle, &SubDeviceCount, SubDevs.data()));
875+
876+
size_t SubDeviceCount_s{SubDeviceCount};
877+
auto ResSize =
878+
std::min(SubDeviceCount_s, propSize / sizeof(ur_device_handle_t));
879+
std::vector<ur_device_handle_t> Res;
880+
for (const auto &d : SubDevs) {
881+
// We can only reach this code if ZE_FLAT_DEVICE_HIERARCHY != FLAT,
882+
// because in flat mode we directly get tiles, and those don't have any
883+
// further divisions, so zeDeviceGetSubDevices always will return an empty
884+
// list. Thus, there's only two options left: (a) composite mode, and (b)
885+
// combined mode. In (b), zeDeviceGet returns tiles as devices, and those
886+
// are presented as root devices (i.e. isSubDevice() returns false). In
887+
// contrast, in (a), zeDeviceGet returns cards as devices, so tiles are
888+
// not root devices (i.e. isSubDevice() returns true). Since we only reach
889+
// this code if there are tiles returned by zeDeviceGetSubDevices, we
890+
// can know if we are in (a) or (b) by checking if a tile is root device
891+
// or not.
892+
ur_device_handle_t URDev = Device->Platform->getDeviceFromNativeHandle(d);
893+
if (URDev->isSubDevice())
894+
// We are in COMPOSITE mode, return an empty list.
895+
return ReturnValue(0);
896+
897+
Res.push_back(URDev);
898+
}
899+
if (pSize)
900+
*pSize = SubDeviceCount * sizeof(ur_device_handle_t);
901+
if (ParamValue) {
902+
return ReturnValue(Res.data(), ResSize);
903+
}
904+
return UR_RESULT_SUCCESS;
905+
}
906+
case UR_DEVICE_INFO_COMPOSITE_DEVICE: {
907+
ur_device_handle_t UrRootDev = nullptr;
908+
ze_device_handle_t DevHandle = Device->ZeDevice;
909+
ze_device_handle_t RootDev;
910+
// Query Root Device.
911+
auto errc = ZE_CALL_NOCHECK(zeDeviceGetRootDevice, (DevHandle, &RootDev));
912+
UrRootDev = Device->Platform->getDeviceFromNativeHandle(RootDev);
913+
if (errc != ZE_RESULT_SUCCESS &&
914+
errc != ZE_RESULT_ERROR_UNSUPPORTED_FEATURE)
915+
return ze2urResult(errc);
916+
return ReturnValue(UrRootDev);
917+
}
918+
829919
default:
830920
urPrint("Unsupported ParamName in urGetDeviceInfo\n");
831921
urPrint("ParamName=%d(0x%x)\n", ParamName, ParamName);

source/adapters/level_zero/platform.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,35 @@ ur_result_t ur_platform_handle_t_::populateDeviceCacheIfNeeded() {
337337
}
338338
delete[] ZeSubdevices;
339339

340+
// When using ZE_FLAT_DEVICE_HIERARCHY=COMBINED, zeDeviceGet will
341+
// return tiles as devices, but we can get the card device handle
342+
// through zeDeviceGetRootDevice. We need to cache the card device
343+
// handle too, such that it is readily visible to the
344+
// urDeviceCreateWithNativeHandle.
345+
ze_device_handle_t RootDevice = nullptr;
346+
// We cannot use ZE2UR_CALL because under some circumstances this call may
347+
// return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, and ZE2UR_CALL will abort
348+
// because it's not UR_RESULT_SUCCESS. Instead, we use ZE_CALL_NOCHECK and
349+
// we check manually that the result is either ZE_RESULT_SUCCESS or
350+
// ZE_RESULT_ERROR_UNSUPPORTED_FEATURE.
351+
auto errc = ZE_CALL_NOCHECK(zeDeviceGetRootDevice,
352+
(Device->ZeDevice, &RootDevice));
353+
if (errc != ZE_RESULT_SUCCESS &&
354+
errc != ZE_RESULT_ERROR_UNSUPPORTED_FEATURE)
355+
return ze2urResult(errc);
356+
357+
if (RootDevice) {
358+
if (std::find_if(URDevicesCache.begin(), URDevicesCache.end(),
359+
[&](auto &Dev) {
360+
return Dev->ZeDevice == RootDevice;
361+
}) == URDevicesCache.end()) {
362+
std::unique_ptr<ur_device_handle_t_> UrRootDevice(
363+
new ur_device_handle_t_(RootDevice, (ur_platform_handle_t)this));
364+
UR_CALL(UrRootDevice->initialize());
365+
URDevicesCache.push_back(std::move(UrRootDevice));
366+
}
367+
}
368+
340369
// Save the root device in the cache for future uses.
341370
URDevicesCache.push_back(std::move(Device));
342371
}

source/adapters/native_cpu/device.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice,
300300
}
301301
case UR_DEVICE_INFO_ESIMD_SUPPORT:
302302
return ReturnValue(false);
303+
case UR_DEVICE_INFO_COMPONENT_DEVICES:
304+
case UR_DEVICE_INFO_COMPOSITE_DEVICE:
305+
// These two are exclusive of L0.
306+
return ReturnValue(0);
303307

304308
CASE_UR_UNSUPPORTED(UR_DEVICE_INFO_MAX_MEMORY_BANDWIDTH);
305309
case UR_DEVICE_INFO_VIRTUAL_MEMORY_SUPPORT:

source/adapters/opencl/device.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urDeviceGetInfo(ur_device_handle_t hDevice,
923923
}
924924
return ReturnValue(SupportedExtensions.c_str());
925925
}
926+
case UR_DEVICE_INFO_COMPONENT_DEVICES:
927+
case UR_DEVICE_INFO_COMPOSITE_DEVICE:
928+
// These two are exclusive of L0.
929+
return ReturnValue(0);
926930
/* TODO: Check regularly to see if support is enabled in OpenCL. Intel GPU
927931
* EU device-specific information extensions. Some of the queries are
928932
* enabled by cl_intel_device_attribute_query extension, but it's not yet in

test/conformance/device/urDeviceGetInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ static std::unordered_map<ur_device_info_t, size_t> device_info_size_map = {
112112
{UR_DEVICE_INFO_MEM_CHANNEL_SUPPORT, sizeof(ur_bool_t)},
113113
{UR_DEVICE_INFO_HOST_PIPE_READ_WRITE_SUPPORTED, sizeof(ur_bool_t)},
114114
{UR_DEVICE_INFO_MAX_REGISTERS_PER_WORK_GROUP, sizeof(uint32_t)},
115+
{UR_DEVICE_INFO_COMPONENT_DEVICES, sizeof(uint32_t)},
116+
{UR_DEVICE_INFO_COMPOSITE_DEVICE, sizeof(ur_device_handle_t)},
115117
};
116118

117119
struct urDeviceGetInfoTest : uur::urAllDevicesTest,

0 commit comments

Comments
 (0)