Skip to content

Commit e7e311e

Browse files
smaslov-intelPavel V Chupin
andauthored
[SYCL][L0] POC for code re-use between PI L0 Plugin and UR L0 Adapter (#7293)
Moved (with slightest changes) the minimal viable amount of L0 Plugin code to form a future Unified Runtime and Unified Runtime L0 Adapter. The same code is used for L0 Plugin and UR. The immediate next step would be to enable build/use of PI UR as a new backend of SYCL RT. Signed-off-by: Sergey V Maslov <[email protected]> Co-authored-by: Pavel V Chupin <[email protected]>
1 parent 10d4ae9 commit e7e311e

File tree

10 files changed

+691
-425
lines changed

10 files changed

+691
-425
lines changed

sycl/plugins/CMakeLists.txt

100644100755
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ foreach(plugin ${SYCL_ENABLE_PLUGINS})
88
add_subdirectory(${plugin})
99
endforeach()
1010

11+
# level_zero plugin depends today on unified_runtime plugin
12+
# and unified_runtime plugin is not an independent plugin, adding it explicitly
13+
if ("level_zero" IN_LIST SYCL_ENABLE_PLUGINS)
14+
add_subdirectory(unified_runtime)
15+
endif()

sycl/plugins/level_zero/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ add_sycl_plugin(level_zero
117117
LIBRARIES
118118
"${LEVEL_ZERO_LOADER}"
119119
Threads::Threads
120+
unified_runtime
120121
)
121122

122123
find_package(Python3 REQUIRED)

sycl/plugins/level_zero/pi_level_zero.cpp

100644100755
Lines changed: 8 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,6 @@ void disableZeTracing();
4242

4343
namespace {
4444

45-
// Controls Level Zero calls serialization to w/a Level Zero driver being not MT
46-
// ready. Recognized values (can be used as a bit mask):
47-
enum {
48-
ZeSerializeNone =
49-
0, // no locking or blocking (except when SYCL RT requested blocking)
50-
ZeSerializeLock = 1, // locking around each ZE_CALL
51-
ZeSerializeBlock =
52-
2, // blocking ZE calls, where supported (usually in enqueue commands)
53-
};
54-
static const pi_uint32 ZeSerialize = [] {
55-
const char *SerializeMode = std::getenv("ZE_SERIALIZE");
56-
const pi_uint32 SerializeModeValue =
57-
SerializeMode ? std::atoi(SerializeMode) : 0;
58-
return SerializeModeValue;
59-
}();
60-
6145
// This is an experimental option to test performance of device to device copy
6246
// operations on copy engines (versus compute engine)
6347
static const bool UseCopyEngineForD2DCopy = [] {
@@ -106,30 +90,6 @@ static const bool ReuseDiscardedEvents = [] {
10690
return std::stoi(ReuseDiscardedEventsFlag) > 0;
10791
}();
10892

109-
// This class encapsulates actions taken along with a call to Level Zero API.
110-
class ZeCall {
111-
private:
112-
// The global mutex that is used for total serialization of Level Zero calls.
113-
static std::mutex GlobalLock;
114-
115-
public:
116-
ZeCall() {
117-
if ((ZeSerialize & ZeSerializeLock) != 0) {
118-
GlobalLock.lock();
119-
}
120-
}
121-
~ZeCall() {
122-
if ((ZeSerialize & ZeSerializeLock) != 0) {
123-
GlobalLock.unlock();
124-
}
125-
}
126-
127-
// The non-static version just calls static one.
128-
ze_result_t doCall(ze_result_t ZeResult, const char *ZeName,
129-
const char *ZeArgs, bool TraceError = true);
130-
};
131-
std::mutex ZeCall::GlobalLock;
132-
13393
// Controls PI level tracing prints.
13494
static bool PrintPiTrace = false;
13595

@@ -139,45 +99,14 @@ static const bool IndirectAccessTrackingEnabled = [] {
13999
nullptr;
140100
}();
141101

142-
// Map Level Zero runtime error code to PI error code.
143-
static pi_result mapError(ze_result_t ZeResult) {
144-
// TODO: these mapping need to be clarified and synced with the PI API return
145-
// values, which is TBD.
146-
static std::unordered_map<ze_result_t, pi_result> ErrorMapping = {
147-
{ZE_RESULT_SUCCESS, PI_SUCCESS},
148-
{ZE_RESULT_ERROR_DEVICE_LOST, PI_ERROR_DEVICE_NOT_FOUND},
149-
{ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, PI_ERROR_INVALID_OPERATION},
150-
{ZE_RESULT_ERROR_NOT_AVAILABLE, PI_ERROR_INVALID_OPERATION},
151-
{ZE_RESULT_ERROR_UNINITIALIZED, PI_ERROR_INVALID_PLATFORM},
152-
{ZE_RESULT_ERROR_INVALID_ARGUMENT, PI_ERROR_INVALID_ARG_VALUE},
153-
{ZE_RESULT_ERROR_INVALID_NULL_POINTER, PI_ERROR_INVALID_VALUE},
154-
{ZE_RESULT_ERROR_INVALID_SIZE, PI_ERROR_INVALID_VALUE},
155-
{ZE_RESULT_ERROR_UNSUPPORTED_SIZE, PI_ERROR_INVALID_VALUE},
156-
{ZE_RESULT_ERROR_UNSUPPORTED_ALIGNMENT, PI_ERROR_INVALID_VALUE},
157-
{ZE_RESULT_ERROR_INVALID_SYNCHRONIZATION_OBJECT, PI_ERROR_INVALID_EVENT},
158-
{ZE_RESULT_ERROR_INVALID_ENUMERATION, PI_ERROR_INVALID_VALUE},
159-
{ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION, PI_ERROR_INVALID_VALUE},
160-
{ZE_RESULT_ERROR_UNSUPPORTED_IMAGE_FORMAT, PI_ERROR_INVALID_VALUE},
161-
{ZE_RESULT_ERROR_INVALID_NATIVE_BINARY, PI_ERROR_INVALID_BINARY},
162-
{ZE_RESULT_ERROR_INVALID_KERNEL_NAME, PI_ERROR_INVALID_KERNEL_NAME},
163-
{ZE_RESULT_ERROR_INVALID_FUNCTION_NAME, PI_ERROR_BUILD_PROGRAM_FAILURE},
164-
{ZE_RESULT_ERROR_OVERLAPPING_REGIONS, PI_ERROR_INVALID_OPERATION},
165-
{ZE_RESULT_ERROR_INVALID_GROUP_SIZE_DIMENSION,
166-
PI_ERROR_INVALID_WORK_GROUP_SIZE},
167-
{ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, PI_ERROR_BUILD_PROGRAM_FAILURE},
168-
{ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY, PI_ERROR_OUT_OF_RESOURCES},
169-
{ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, PI_ERROR_OUT_OF_HOST_MEMORY}};
170-
171-
auto It = ErrorMapping.find(ZeResult);
172-
if (It == ErrorMapping.end()) {
173-
return PI_ERROR_UNKNOWN;
174-
}
175-
return It->second;
176-
}
177-
178102
// This will count the calls to Level-Zero
179103
static std::map<const char *, int> *ZeCallCount = nullptr;
180104

105+
// Map from L0 to PI result
106+
static inline pi_result mapError(ze_result_t Result) {
107+
return ur2piResult(ze2urResult(Result));
108+
}
109+
181110
// Trace a call to Level-Zero RT
182111
#define ZE_CALL(ZeName, ZeArgs) \
183112
{ \
@@ -186,9 +115,6 @@ static std::map<const char *, int> *ZeCallCount = nullptr;
186115
return mapError(Result); \
187116
}
188117

189-
#define ZE_CALL_NOCHECK(ZeName, ZeArgs) \
190-
ZeCall().doCall(ZeName ZeArgs, #ZeName, #ZeArgs, false)
191-
192118
// Trace an internal PI call; returns in case of an error.
193119
#define PI_CALL(Call) \
194120
{ \
@@ -199,29 +125,6 @@ static std::map<const char *, int> *ZeCallCount = nullptr;
199125
return Result; \
200126
}
201127

202-
enum DebugLevel {
203-
ZE_DEBUG_NONE = 0x0,
204-
ZE_DEBUG_BASIC = 0x1,
205-
ZE_DEBUG_VALIDATION = 0x2,
206-
ZE_DEBUG_CALL_COUNT = 0x4,
207-
ZE_DEBUG_ALL = -1
208-
};
209-
210-
// Controls Level Zero calls tracing.
211-
static const int ZeDebug = [] {
212-
const char *DebugMode = std::getenv("ZE_DEBUG");
213-
return DebugMode ? std::atoi(DebugMode) : ZE_DEBUG_NONE;
214-
}();
215-
216-
static void zePrint(const char *Format, ...) {
217-
if (ZeDebug & ZE_DEBUG_BASIC) {
218-
va_list Args;
219-
va_start(Args, Format);
220-
vfprintf(stderr, Format, Args);
221-
va_end(Args);
222-
}
223-
}
224-
225128
// Controls if we should choose doing eager initialization
226129
// to make it happen on warmup paths and have the reportable
227130
// paths be less likely affected.
@@ -459,10 +362,6 @@ static sycl::detail::SpinLock *PiPlatformsCacheMutex =
459362
new sycl::detail::SpinLock;
460363
static bool PiPlatformCachePopulated = false;
461364

462-
// Flags which tell whether various Level Zero extensions are available.
463-
static bool PiDriverGlobalOffsetExtensionFound = false;
464-
static bool PiDriverModuleProgramExtensionFound = false;
465-
466365
pi_result
467366
_pi_context::getFreeSlotInExistingOrNewPool(ze_event_pool_handle_t &Pool,
468367
size_t &Index, bool HostVisible,
@@ -2313,123 +2212,6 @@ static ze_result_t
23132212
checkUnresolvedSymbols(ze_module_handle_t ZeModule,
23142213
ze_module_build_log_handle_t *ZeBuildLog);
23152214

2316-
// This function will ensure compatibility with both Linux and Windows for
2317-
// setting environment variables.
2318-
static bool setEnvVar(const char *name, const char *value) {
2319-
#ifdef _WIN32
2320-
int Res = _putenv_s(name, value);
2321-
#else
2322-
int Res = setenv(name, value, 1);
2323-
#endif
2324-
if (Res != 0) {
2325-
zePrint(
2326-
"Level Zero plugin was unable to set the environment variable: %s\n",
2327-
name);
2328-
return false;
2329-
}
2330-
return true;
2331-
}
2332-
2333-
static class ZeUSMImportExtension {
2334-
// Pointers to functions that import/release host memory into USM
2335-
ze_result_t (*zexDriverImportExternalPointer)(ze_driver_handle_t hDriver,
2336-
void *, size_t);
2337-
ze_result_t (*zexDriverReleaseImportedPointer)(ze_driver_handle_t, void *);
2338-
2339-
public:
2340-
// Whether user has requested Import/Release, and platform supports it.
2341-
bool Enabled;
2342-
2343-
ZeUSMImportExtension() : Enabled{false} {}
2344-
2345-
void setZeUSMImport(pi_platform Platform) {
2346-
// Whether env var SYCL_USM_HOSTPTR_IMPORT has been set requesting
2347-
// host ptr import during buffer creation.
2348-
const char *USMHostPtrImportStr = std::getenv("SYCL_USM_HOSTPTR_IMPORT");
2349-
if (!USMHostPtrImportStr || std::atoi(USMHostPtrImportStr) == 0)
2350-
return;
2351-
2352-
// Check if USM hostptr import feature is available.
2353-
ze_driver_handle_t driverHandle = Platform->ZeDriver;
2354-
if (ZE_CALL_NOCHECK(zeDriverGetExtensionFunctionAddress,
2355-
(driverHandle, "zexDriverImportExternalPointer",
2356-
reinterpret_cast<void **>(
2357-
&zexDriverImportExternalPointer))) == 0) {
2358-
ZE_CALL_NOCHECK(
2359-
zeDriverGetExtensionFunctionAddress,
2360-
(driverHandle, "zexDriverReleaseImportedPointer",
2361-
reinterpret_cast<void **>(&zexDriverReleaseImportedPointer)));
2362-
// Hostptr import/release is turned on because it has been requested
2363-
// by the env var, and this platform supports the APIs.
2364-
Enabled = true;
2365-
// Hostptr import is only possible if piMemBufferCreate receives a
2366-
// hostptr as an argument. The SYCL runtime passes a host ptr
2367-
// only when SYCL_HOST_UNIFIED_MEMORY is enabled. Therefore we turn it on.
2368-
setEnvVar("SYCL_HOST_UNIFIED_MEMORY", "1");
2369-
}
2370-
}
2371-
void doZeUSMImport(ze_driver_handle_t driverHandle, void *HostPtr,
2372-
size_t Size) {
2373-
ZE_CALL_NOCHECK(zexDriverImportExternalPointer,
2374-
(driverHandle, HostPtr, Size));
2375-
}
2376-
void doZeUSMRelease(ze_driver_handle_t driverHandle, void *HostPtr) {
2377-
ZE_CALL_NOCHECK(zexDriverReleaseImportedPointer, (driverHandle, HostPtr));
2378-
}
2379-
} ZeUSMImport;
2380-
2381-
pi_result _pi_platform::initialize() {
2382-
// Cache driver properties
2383-
ZeStruct<ze_driver_properties_t> ZeDriverProperties;
2384-
ZE_CALL(zeDriverGetProperties, (ZeDriver, &ZeDriverProperties));
2385-
uint32_t DriverVersion = ZeDriverProperties.driverVersion;
2386-
// Intel Level-Zero GPU driver stores version as:
2387-
// | 31 - 24 | 23 - 16 | 15 - 0 |
2388-
// | Major | Minor | Build |
2389-
auto VersionMajor = std::to_string((DriverVersion & 0xFF000000) >> 24);
2390-
auto VersionMinor = std::to_string((DriverVersion & 0x00FF0000) >> 16);
2391-
auto VersionBuild = std::to_string(DriverVersion & 0x0000FFFF);
2392-
ZeDriverVersion = VersionMajor + "." + VersionMinor + "." + VersionBuild;
2393-
2394-
ZE_CALL(zeDriverGetApiVersion, (ZeDriver, &ZeApiVersion));
2395-
ZeDriverApiVersion = std::to_string(ZE_MAJOR_VERSION(ZeApiVersion)) + "." +
2396-
std::to_string(ZE_MINOR_VERSION(ZeApiVersion));
2397-
2398-
// Cache driver extension properties
2399-
uint32_t Count = 0;
2400-
ZE_CALL(zeDriverGetExtensionProperties, (ZeDriver, &Count, nullptr));
2401-
2402-
std::vector<ze_driver_extension_properties_t> zeExtensions(Count);
2403-
2404-
ZE_CALL(zeDriverGetExtensionProperties,
2405-
(ZeDriver, &Count, zeExtensions.data()));
2406-
2407-
for (auto extension : zeExtensions) {
2408-
// Check if global offset extension is available
2409-
if (strncmp(extension.name, ZE_GLOBAL_OFFSET_EXP_NAME,
2410-
strlen(ZE_GLOBAL_OFFSET_EXP_NAME) + 1) == 0) {
2411-
if (extension.version == ZE_GLOBAL_OFFSET_EXP_VERSION_1_0) {
2412-
PiDriverGlobalOffsetExtensionFound = true;
2413-
}
2414-
}
2415-
// Check if extension is available for "static linking" (compiling multiple
2416-
// SPIR-V modules together into one Level Zero module).
2417-
if (strncmp(extension.name, ZE_MODULE_PROGRAM_EXP_NAME,
2418-
strlen(ZE_MODULE_PROGRAM_EXP_NAME) + 1) == 0) {
2419-
if (extension.version == ZE_MODULE_PROGRAM_EXP_VERSION_1_0) {
2420-
PiDriverModuleProgramExtensionFound = true;
2421-
}
2422-
}
2423-
zeDriverExtensionMap[extension.name] = extension.version;
2424-
}
2425-
2426-
// Check if import user ptr into USM feature has been requested.
2427-
// If yes, then set up L0 API pointers if the platform supports it.
2428-
ZeUSMImport.setZeUSMImport(this);
2429-
2430-
return PI_SUCCESS;
2431-
}
2432-
24332215
pi_result piPlatformsGet(pi_uint32 NumEntries, pi_platform *Platforms,
24342216
pi_uint32 *NumPlatforms) {
24352217

@@ -4886,7 +4668,8 @@ pi_result piProgramLink(pi_context Context, pi_uint32 NumDevices,
48864668
// input module.
48874669
//
48884670
// TODO: Remove this workaround when the driver is fixed.
4889-
if (!PiDriverModuleProgramExtensionFound || (NumInputPrograms == 1)) {
4671+
if (!DeviceList[0]->Platform->ZeDriverModuleProgramExtensionFound ||
4672+
(NumInputPrograms == 1)) {
48904673
if (NumInputPrograms == 1) {
48914674
ZeModuleDesc.pNext = nullptr;
48924675
ZeModuleDesc.inputSize = ZeExtModuleDesc.inputSizes[0];
@@ -5525,7 +5308,7 @@ piEnqueueKernelLaunch(pi_queue Queue, pi_kernel Kernel, pi_uint32 WorkDim,
55255308
std::scoped_lock<pi_shared_mutex, pi_shared_mutex, pi_shared_mutex> Lock(
55265309
Queue->Mutex, Kernel->Mutex, Kernel->Program->Mutex);
55275310
if (GlobalWorkOffset != NULL) {
5528-
if (!PiDriverGlobalOffsetExtensionFound) {
5311+
if (!Queue->Device->Platform->ZeDriverGlobalOffsetExtensionFound) {
55295312
zePrint("No global offset extension found on this driver\n");
55305313
return PI_ERROR_INVALID_VALUE;
55315314
}

0 commit comments

Comments
 (0)