Skip to content

[SYCL] properly report supported device partitioning in Level-Zero #2751

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 3 commits into from
Nov 12, 2020
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
13 changes: 10 additions & 3 deletions sycl/plugins/level_zero/pi_level_zero.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1232,11 +1232,18 @@ pi_result piDeviceGetInfo(pi_device Device, pi_device_info ParamName,
case PI_DEVICE_INFO_REFERENCE_COUNT:
return ReturnValue(pi_uint32{Device->RefCount});
case PI_DEVICE_INFO_PARTITION_PROPERTIES: {
// SYCL spec says: if this SYCL device cannot be partitioned into at least
// two sub devices then the returned vector must be empty.
uint32_t ZeSubDeviceCount = 0;
ZE_CALL(zeDeviceGetSubDevices(ZeDevice, &ZeSubDeviceCount, nullptr));
if (ZeSubDeviceCount < 2) {
return ReturnValue(pi_device_partition_property{0});
}
// It is debatable if SYCL sub-device and partitioning APIs sufficient to
// expose Level Zero sub-devices? We start with support of
// "partition_by_affinity_domain" and "numa" but if that doesn't seem to
// be a good fit we could look at adding a more descriptive partitioning
// type.
// "partition_by_affinity_domain" and "next_partitionable" but if that
// doesn't seem to be a good fit we could look at adding a more descriptive
// partitioning type.
struct {
pi_device_partition_property Arr[2];
} PartitionProperties = {{PI_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, 0}};
Expand Down
94 changes: 94 additions & 0 deletions sycl/test/on-device/basic_tests/partition_supported.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %CPU_RUN_PLACEHOLDER %t.out
// RUN: %GPU_RUN_PLACEHOLDER %t.out
// RUN: %ACC_RUN_PLACEHOLDER %t.out

/* Check that:
1) [info::device::partition_properties]: returns the partition properties
supported by this SYCL device; a vector of info::partition_property. If this
SYCL device cannot be partitioned into at least two sub devices then the
returned vector **must be empty**.

2) [create_sub_devices()]: If the SYCL device
does not support info::partition_property::partition_by_affinity_domain or the
SYCL device does not support the info::partition_affinity_domain provided, an
exception with the **feature_not_supported error code must be thrown**.
*/

#include <CL/sycl.hpp>

/** returns true if the device supports a particular affinity domain
*/
static bool
supports_affinity_domain(const cl::sycl::device &dev,
cl::sycl::info::partition_property partitionProp,
cl::sycl::info::partition_affinity_domain domain) {
if (partitionProp !=
cl::sycl::info::partition_property::partition_by_affinity_domain) {
return true;
}
auto supported =
dev.get_info<cl::sycl::info::device::partition_affinity_domains>();
for (cl::sycl::info::partition_affinity_domain dom : supported) {
if (dom == domain) {
return true;
}
}
return false;
}

/** returns true if the device supports a particular partition property
*/
static bool
supports_partition_property(const cl::sycl::device &dev,
cl::sycl::info::partition_property partitionProp) {
auto supported = dev.get_info<cl::sycl::info::device::partition_properties>();
for (cl::sycl::info::partition_property prop : supported) {
if (prop == partitionProp) {
return true;
}
}
return false;
}

int main() {

auto dev = cl::sycl::device(cl::sycl::default_selector());

cl::sycl::info::partition_property partitionProperty =
cl::sycl::info::partition_property::partition_by_affinity_domain;
cl::sycl::info::partition_affinity_domain affinityDomain =
cl::sycl::info::partition_affinity_domain::next_partitionable;

if (supports_partition_property(dev, partitionProperty)) {
if (supports_affinity_domain(dev, partitionProperty, affinityDomain)) {
auto subDevices = dev.create_sub_devices<
cl::sycl::info::partition_property::partition_by_affinity_domain>(
affinityDomain);

if (subDevices.size() < 2) {
std::cerr << "device::create_sub_device(info::partition_affinity_"
"domain) should have returned at least 2 devices"
<< std::endl;
return -1;
}
}
} else {
try {
auto subDevices = dev.create_sub_devices<
cl::sycl::info::partition_property::partition_by_affinity_domain>(
affinityDomain);
std::cerr << "device::create_sub_device(info::partition_affinity_domain) "
"should have thrown an exception"
<< std::endl;
return -1;
} catch (const cl::sycl::feature_not_supported &e) {
} catch (...) {
std::cerr << "device::create_sub_device(info::partition_affinity_domain) "
"should have thrown cl::sycl::feature_not_supported"
<< std::endl;
return -1;
}
}
return 0;
}