Skip to content

[SYCL] Add ext_oneapi_unified_runtime SYCL backend #7816

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 7 commits into from
Dec 23, 2022
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
4 changes: 4 additions & 0 deletions sycl/include/sycl/backend_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum class backend : char {
ext_intel_esimd_emulator,
ext_oneapi_hip = 6,
hip __SYCL2020_DEPRECATED("use 'ext_oneapi_hip' instead") = ext_oneapi_hip,
ext_oneapi_unified_runtime = 7,
};

template <backend Backend> class backend_traits;
Expand Down Expand Up @@ -63,6 +64,9 @@ inline std::ostream &operator<<(std::ostream &Out, backend be) {
case backend::ext_oneapi_hip:
Out << "ext_oneapi_hip";
break;
case backend::ext_oneapi_unified_runtime:
Out << "ext_oneapi_unified_runtime";
break;
case backend::all:
Out << "all";
}
Expand Down
3 changes: 3 additions & 0 deletions sycl/include/sycl/detail/pi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,21 @@ bool trace(TraceLevel level);
#define __SYCL_CUDA_PLUGIN_NAME "pi_cuda.dll"
#define __SYCL_ESIMD_EMULATOR_PLUGIN_NAME "pi_esimd_emulator.dll"
#define __SYCL_HIP_PLUGIN_NAME "libpi_hip.dll"
#define __SYCL_UNIFIED_RUNTIME_PLUGIN_NAME "pi_unified_runtime.dll"
#elif defined(__SYCL_RT_OS_LINUX)
#define __SYCL_OPENCL_PLUGIN_NAME "libpi_opencl.so"
#define __SYCL_LEVEL_ZERO_PLUGIN_NAME "libpi_level_zero.so"
#define __SYCL_CUDA_PLUGIN_NAME "libpi_cuda.so"
#define __SYCL_ESIMD_EMULATOR_PLUGIN_NAME "libpi_esimd_emulator.so"
#define __SYCL_UNIFIED_RUNTIME_PLUGIN_NAME "libpi_unified_runtime.so"
#define __SYCL_HIP_PLUGIN_NAME "libpi_hip.so"
#elif defined(__SYCL_RT_OS_DARWIN)
#define __SYCL_OPENCL_PLUGIN_NAME "libpi_opencl.dylib"
#define __SYCL_LEVEL_ZERO_PLUGIN_NAME "libpi_level_zero.dylib"
#define __SYCL_CUDA_PLUGIN_NAME "libpi_cuda.dylib"
#define __SYCL_ESIMD_EMULATOR_PLUGIN_NAME "libpi_esimd_emulator.dylib"
#define __SYCL_HIP_PLUGIN_NAME "libpi_hip.dylib"
#define __SYCL_UNIFIED_RUNTIME_PLUGIN_NAME "libpi_unified_runtime.dylib"
#else
#error "Unsupported OS"
#endif
Expand Down
143 changes: 11 additions & 132 deletions sycl/plugins/level_zero/pi_level_zero.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,87 +198,6 @@ template <> ze_result_t zeHostSynchronize(ze_command_queue_handle_t Handle) {
return zeHostSynchronizeImpl(zeCommandQueueSynchronize, Handle);
}

template <typename T, typename Assign>
pi_result getInfoImpl(size_t param_value_size, void *param_value,
size_t *param_value_size_ret, T value, size_t value_size,
Assign &&assign_func) {

if (param_value != nullptr) {

if (param_value_size < value_size) {
return PI_ERROR_INVALID_VALUE;
}

assign_func(param_value, value, value_size);
}

if (param_value_size_ret != nullptr) {
*param_value_size_ret = value_size;
}

return PI_SUCCESS;
}

template <typename T>
pi_result getInfo(size_t param_value_size, void *param_value,
size_t *param_value_size_ret, T value) {

auto assignment = [](void *param_value, T value, size_t value_size) {
(void)value_size;
*static_cast<T *>(param_value) = value;
};

return getInfoImpl(param_value_size, param_value, param_value_size_ret, value,
sizeof(T), assignment);
}

template <typename T>
pi_result getInfoArray(size_t array_length, size_t param_value_size,
void *param_value, size_t *param_value_size_ret,
T *value) {
return getInfoImpl(param_value_size, param_value, param_value_size_ret, value,
array_length * sizeof(T), memcpy);
}

template <typename T, typename RetType>
pi_result getInfoArray(size_t array_length, size_t param_value_size,
void *param_value, size_t *param_value_size_ret,
T *value) {
if (param_value) {
memset(param_value, 0, param_value_size);
for (uint32_t I = 0; I < array_length; I++)
((RetType *)param_value)[I] = (RetType)value[I];
}
if (param_value_size_ret)
*param_value_size_ret = array_length * sizeof(RetType);
return PI_SUCCESS;
}

template <>
pi_result getInfo<const char *>(size_t param_value_size, void *param_value,
size_t *param_value_size_ret,
const char *value) {
return getInfoArray(strlen(value) + 1, param_value_size, param_value,
param_value_size_ret, value);
}

class ReturnHelper {
public:
ReturnHelper(size_t param_value_size, void *param_value,
size_t *param_value_size_ret)
: param_value_size(param_value_size), param_value(param_value),
param_value_size_ret(param_value_size_ret) {}

template <class T> pi_result operator()(const T &t) {
return getInfo(param_value_size, param_value, param_value_size_ret, t);
}

private:
size_t param_value_size;
void *param_value;
size_t *param_value_size_ret;
};

} // anonymous namespace

// SYCL_PI_LEVEL_ZERO_USE_COMPUTE_ENGINE can be set to an integer (>=0) in
Expand Down Expand Up @@ -439,11 +358,6 @@ pi_result _pi_context::decrementUnreleasedEventsInPool(pi_event Event) {
return PI_SUCCESS;
}

// Some opencl extensions we know are supported by all Level Zero devices.
constexpr char ZE_SUPPORTED_EXTENSIONS[] =
"cl_khr_il_program cl_khr_subgroups cl_intel_subgroups "
"cl_intel_subgroups_short cl_intel_required_subgroup_size ";

// Forward declarations
static pi_result
enqueueMemCopyHelper(pi_command_type CommandType, pi_queue Queue, void *Dst,
Expand Down Expand Up @@ -2307,51 +2221,17 @@ pi_result piPlatformsGet(pi_uint32 NumEntries, pi_platform *Platforms,
pi_result piPlatformGetInfo(pi_platform Platform, pi_platform_info ParamName,
size_t ParamValueSize, void *ParamValue,
size_t *ParamValueSizeRet) {

PI_ASSERT(Platform, PI_ERROR_INVALID_PLATFORM);

zePrint("==========================\n");
zePrint("SYCL over Level-Zero %s\n", Platform->ZeDriverVersion.c_str());
zePrint("==========================\n");

ReturnHelper ReturnValue(ParamValueSize, ParamValue, ParamValueSizeRet);

switch (ParamName) {
case PI_PLATFORM_INFO_NAME:
// TODO: Query Level Zero driver when relevant info is added there.
// To distinguish this L0 platform from Unified Runtime one.
if (ParamName == PI_PLATFORM_INFO_NAME) {
ReturnHelper ReturnValue(ParamValueSize, ParamValue, ParamValueSizeRet);
return ReturnValue("Intel(R) Level-Zero");
case PI_PLATFORM_INFO_VENDOR:
// TODO: Query Level Zero driver when relevant info is added there.
return ReturnValue("Intel(R) Corporation");
case PI_PLATFORM_INFO_EXTENSIONS:
// Convention adopted from OpenCL:
// "Returns a space-separated list of extension names (the extension
// names themselves do not contain any spaces) supported by the platform.
// Extensions defined here must be supported by all devices associated
// with this platform."
//
// TODO: Check the common extensions supported by all connected devices and
// return them. For now, hardcoding some extensions we know are supported by
// all Level Zero devices.
return ReturnValue(ZE_SUPPORTED_EXTENSIONS);
case PI_PLATFORM_INFO_PROFILE:
// TODO: figure out what this means and how is this used
return ReturnValue("FULL_PROFILE");
case PI_PLATFORM_INFO_VERSION:
// TODO: this should query to zeDriverGetDriverVersion
// but we don't yet have the driver handle here.
//
// From OpenCL 2.1: "This version string has the following format:
// OpenCL<space><major_version.minor_version><space><platform-specific
// information>. Follow the same notation here.
//
return ReturnValue(Platform->ZeDriverApiVersion.c_str());
default:
zePrint("piPlatformGetInfo: unrecognized ParamName\n");
return PI_ERROR_INVALID_VALUE;
}

return PI_SUCCESS;
return pi2ur::piPlatformGetInfo(Platform, ParamName, ParamValueSize,
ParamValue, ParamValueSizeRet);
}

pi_result piextPlatformGetNativeHandle(pi_platform Platform,
Expand Down Expand Up @@ -3068,10 +2948,9 @@ pi_result piDeviceGetInfo(pi_device Device, pi_device_info ParamName,
case PI_DEVICE_INFO_SUB_GROUP_SIZES_INTEL: {
// ze_device_compute_properties.subGroupSizes is in uint32_t whereas the
// expected return is size_t datatype. size_t can be 8 bytes of data.
return getInfoArray<uint32_t, size_t>(
Device->ZeDeviceComputeProperties->numSubGroupSizes, ParamValueSize,
ParamValue, ParamValueSizeRet,
Device->ZeDeviceComputeProperties->subGroupSizes);
return ReturnValue.template operator()<size_t>(
Device->ZeDeviceComputeProperties->subGroupSizes,
Device->ZeDeviceComputeProperties->numSubGroupSizes);
}
case PI_DEVICE_INFO_IL_VERSION: {
// Set to a space separated list of IL version strings of the form
Expand Down Expand Up @@ -3463,8 +3342,7 @@ pi_result piContextGetInfo(pi_context Context, pi_context_info ParamName,
ReturnHelper ReturnValue(ParamValueSize, ParamValue, ParamValueSizeRet);
switch (ParamName) {
case PI_CONTEXT_INFO_DEVICES:
return getInfoArray(Context->Devices.size(), ParamValueSize, ParamValue,
ParamValueSizeRet, &Context->Devices[0]);
return ReturnValue(&Context->Devices[0], Context->Devices.size());
case PI_CONTEXT_INFO_NUM_DEVICES:
return ReturnValue(pi_uint32(Context->Devices.size()));
case PI_CONTEXT_INFO_REFERENCE_COUNT:
Expand Down Expand Up @@ -5375,7 +5253,8 @@ pi_result piKernelGetGroupInfo(pi_kernel Kernel, pi_device Device,
return ReturnValue(WorkSize);
}
case PI_KERNEL_GROUP_INFO_WORK_GROUP_SIZE: {
// As of right now, L0 is missing API to query kernel and device specific max work group size.
// As of right now, L0 is missing API to query kernel and device specific
// max work group size.
return ReturnValue(
pi_uint64{Device->ZeDeviceComputeProperties->maxTotalGroupSize});
}
Expand Down
61 changes: 45 additions & 16 deletions sycl/plugins/unified_runtime/pi2ur.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@

// Map of UR error codes to PI error codes
static pi_result ur2piResult(zer_result_t urResult) {

// TODO: replace "global lifetime" objects with a non-trivial d'tor with
// either pointers to such objects (which would be allocated and dealocated
// during init and teardown) or objects with trivial d'tor.
// E.g. for this case we could have an std::array with sorted values.
//
static std::unordered_map<zer_result_t, pi_result> ErrorMapping = {
std::unordered_map<zer_result_t, pi_result> ErrorMapping = {
{ZER_RESULT_SUCCESS, PI_SUCCESS},
{ZER_RESULT_ERROR_UNKNOWN, PI_ERROR_UNKNOWN},
{ZER_RESULT_ERROR_DEVICE_LOST, PI_ERROR_DEVICE_NOT_FOUND},
Expand Down Expand Up @@ -50,6 +44,24 @@ static pi_result ur2piResult(zer_result_t urResult) {
if (auto Result = urCall) \
return ur2piResult(Result);

// A version of return helper that returns pi_result and not zer_result_t
class ReturnHelper : public UrReturnHelper {
public:
using UrReturnHelper::UrReturnHelper;

template <class T> pi_result operator()(const T &t) {
return ur2piResult(UrReturnHelper::operator()(t));
}
// Array return value
template <class T> pi_result operator()(const T *t, size_t s) {
return ur2piResult(UrReturnHelper::operator()(t, s));
}
// Array return value where element type is differrent from T
template <class RetType, class T> pi_result operator()(const T *t, size_t s) {
return ur2piResult(UrReturnHelper::operator()<RetType>(t, s));
}
};

namespace pi2ur {
inline pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms,
pi_uint32 *num_platforms) {
Expand All @@ -66,14 +78,31 @@ inline pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms,
}

inline pi_result piPlatformGetInfo(pi_platform platform,
pi_platform_info param_name,
size_t param_value_size, void *param_value,
size_t *param_value_size_ret) {
(void)platform;
(void)param_name;
(void)param_value_size;
(void)param_value;
(void)param_value_size_ret;
die("Unified Runtime: piPlatformGetInfo is not implemented");
pi_platform_info ParamName,
size_t ParamValueSize, void *ParamValue,
size_t *ParamValueSizeRet) {

static std::unordered_map<pi_platform_info, zer_platform_info_t> InfoMapping =
{
{PI_PLATFORM_INFO_EXTENSIONS, ZER_PLATFORM_INFO_NAME},
{PI_PLATFORM_INFO_NAME, ZER_PLATFORM_INFO_NAME},
{PI_PLATFORM_INFO_PROFILE, ZER_PLATFORM_INFO_PROFILE},
{PI_PLATFORM_INFO_VENDOR, ZER_PLATFORM_INFO_VENDOR_NAME},
{PI_PLATFORM_INFO_VERSION, ZER_PLATFORM_INFO_VERSION},
};

auto InfoType = InfoMapping.find(ParamName);
if (InfoType == InfoMapping.end()) {
return PI_ERROR_UNKNOWN;
}

size_t SizeInOut = ParamValueSize;
auto hPlatform = reinterpret_cast<zer_platform_handle_t>(platform);
HANDLE_ERRORS(
zerPlatformGetInfo(hPlatform, InfoType->second, &SizeInOut, ParamValue));
if (ParamValueSizeRet) {
*ParamValueSizeRet = SizeInOut;
}
return PI_SUCCESS;
}
} // namespace pi2ur
67 changes: 67 additions & 0 deletions sycl/plugins/unified_runtime/pi_unified_runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,79 @@
//
//===------------------------------------------------------------------===//

#include <cstring>

#include <pi2ur.hpp>
#include <pi_unified_runtime.hpp>

// Stub function to where all not yet supported PI API are bound
static void DieUnsupported() {
die("Unified Runtime: functionality is not supported");
}

// All PI API interfaces are C interfaces
extern "C" {
__SYCL_EXPORT pi_result piPlatformsGet(pi_uint32 num_entries,
pi_platform *platforms,
pi_uint32 *num_platforms) {
return pi2ur::piPlatformsGet(num_entries, platforms, num_platforms);
}

__SYCL_EXPORT pi_result piPlatformGetInfo(pi_platform Platform,
pi_platform_info ParamName,
size_t ParamValueSize,
void *ParamValue,
size_t *ParamValueSizeRet) {
return pi2ur::piPlatformGetInfo(Platform, ParamName, ParamValueSize,
ParamValue, ParamValueSizeRet);
}

__SYCL_EXPORT pi_result piDevicesGet(pi_platform Platform,
pi_device_type DeviceType,
pi_uint32 NumEntries, pi_device *Devices,
pi_uint32 *NumDevices) {
// Report no devices, stab to have a minimal SYCL test running
if (NumDevices) {
*NumDevices = 0;
}
return PI_SUCCESS;
}

// This interface is not in Unified Runtime currently
__SYCL_EXPORT pi_result piTearDown(void *) { return PI_SUCCESS; }

// This interface is not in Unified Runtime currently
__SYCL_EXPORT pi_result piPluginInit(pi_plugin *PluginInit) {
PI_ASSERT(PluginInit, PI_ERROR_INVALID_VALUE);

const char SupportedVersion[] = _PI_UNIFIED_RUNTIME_PLUGIN_VERSION_STRING;

// Check that the major version matches in PiVersion and SupportedVersion
_PI_PLUGIN_VERSION_CHECK(PluginInit->PiVersion, SupportedVersion);

// TODO: handle versioning/targets properly.
size_t PluginVersionSize = sizeof(PluginInit->PluginVersion);

PI_ASSERT(strlen(_PI_UNIFIED_RUNTIME_PLUGIN_VERSION_STRING) <
PluginVersionSize,
PI_ERROR_INVALID_VALUE);

strncpy(PluginInit->PluginVersion, SupportedVersion, PluginVersionSize);

// Bind interfaces that are already supported and "die" for unsupported ones
#define _PI_API(api) \
(PluginInit->PiFunctionTable).api = (decltype(&::api))(&DieUnsupported);
#include <sycl/detail/pi.def>

#define _PI_API(api) \
(PluginInit->PiFunctionTable).api = (decltype(&::api))(&api);

_PI_API(piPlatformsGet)
_PI_API(piPlatformGetInfo)
_PI_API(piDevicesGet)
_PI_API(piTearDown)

return PI_SUCCESS;
}

} // extern "C
Loading