Skip to content

Commit d10dd68

Browse files
authored
Level zero codegen (#250)
* WIP level zero support. * Add support to build a SYCL program from SPIR-V. * Ignore the generated config file. * Skip test on Windows. * Black formatting. * Skip test properly. * Fix comment. * Fix black error. * Fix comments. * Fix potential issue on Windows. * Make level zero a dynamically loaded library. * Do not install helper headers and run tests during linux build. * Cleanups...
1 parent 57d41fa commit d10dd68

File tree

4 files changed

+160
-20
lines changed

4 files changed

+160
-20
lines changed

dpctl-capi/CMakeLists.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ if(DPCTL_ENABLE_LO_PROGRAM_CREATION)
9494
PRIVATE
9595
${LEVEL_ZERO_INCLUDE_DIR}
9696
)
97-
target_link_libraries(DPCTLSyclInterface
98-
PRIVATE ${LEVEL_ZERO_LIBRARY}
99-
)
10097
else()
10198
message(WARNING
10299
"DPCTL support Level Zero program creation not supported "
@@ -124,12 +121,6 @@ foreach(HEADER ${HEADERS})
124121
install(FILES "${HEADER}" DESTINATION include/Support)
125122
endforeach()
126123

127-
# Install all headers in helper/include
128-
file(GLOB HEADERS "${CMAKE_SOURCE_DIR}/helper/include/*.h")
129-
foreach(HEADER ${HEADERS})
130-
install(FILES "${HEADER}" DESTINATION helper/include)
131-
endforeach()
132-
133124
# Install all headers in include/Config
134125
file(GLOB HEADERS "${CMAKE_SOURCE_DIR}/include/Config/*.h")
135126
foreach(HEADER ${HEADERS})
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===--------------- dpctl_dynamic_lib_helper.h - dpctl-C_API -*-C++-*-===//
2+
//
3+
// Data Parallel Control Library (dpCtl)
4+
//
5+
// Copyright 2020 Intel Corporation
6+
//
7+
// Licensed under the Apache License, Version 2.0 (the "License");
8+
// you may not use this file except in compliance with the License.
9+
// You may obtain a copy of the License at
10+
//
11+
// http://www.apache.org/licenses/LICENSE-2.0
12+
//
13+
// Unless required by applicable law or agreed to in writing, software
14+
// distributed under the License is distributed on an "AS IS" BASIS,
15+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
// See the License for the specific language governing permissions and
17+
// limitations under the License.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
///
21+
/// \file
22+
/// Helper for dynamic libs management.
23+
//===----------------------------------------------------------------------===//
24+
25+
#ifndef __DPCTL_DYNAMIC_LIB_HELPER_H__
26+
#define __DPCTL_DYNAMIC_LIB_HELPER_H__
27+
28+
#if defined(__linux__) || defined(_WIN32) || defined(_WIN64)
29+
30+
#ifdef __linux__
31+
32+
#include <dlfcn.h>
33+
34+
#elif defined(_WIN32) || defined(_WIN64)
35+
36+
#define NOMINMAX
37+
#include <windows.h>
38+
39+
#endif // __linux__
40+
41+
#include <cstdint>
42+
43+
namespace dpctl
44+
{
45+
46+
class DynamicLibHelper final
47+
{
48+
public:
49+
DynamicLibHelper() = delete;
50+
DynamicLibHelper(const DynamicLibHelper &) = delete;
51+
DynamicLibHelper(const char * libName, int flag)
52+
{
53+
54+
#ifdef __linux__
55+
_handle = dlopen(libName, flag);
56+
#elif defined(_WIN32) || defined(_WIN64)
57+
_handle = LoadLibraryA(libName);
58+
#endif
59+
}
60+
61+
~DynamicLibHelper()
62+
{
63+
#ifdef __linux__
64+
dlclose(_handle);
65+
#elif defined(_WIN32) || defined(_WIN64)
66+
FreeLibrary((HMODULE)_handle);
67+
#endif
68+
};
69+
70+
template <typename T>
71+
T getSymbol(const char * symName)
72+
{
73+
#ifdef __linux__
74+
void * sym = dlsym(_handle, symName);
75+
char * error = dlerror();
76+
77+
if (NULL != error)
78+
{
79+
return nullptr;
80+
}
81+
#elif defined(_WIN32) || defined(_WIN64)
82+
void * sym = (void *)GetProcAddress((HMODULE)_handle, symName);
83+
84+
if (NULL == sym)
85+
{
86+
return nullptr;
87+
}
88+
#endif
89+
90+
return (T)sym;
91+
}
92+
93+
bool opened () const
94+
{
95+
if (!_handle)
96+
return false;
97+
else
98+
return true;
99+
}
100+
101+
private:
102+
void * _handle = nullptr;
103+
};
104+
105+
} // namespace dpctl
106+
107+
#endif // #if defined(__linux__) || defined(_WIN32) || defined(_WIN64)
108+
#endif // __DPCTL_DYNAMIC_LIB_HELPER_H__

dpctl-capi/source/dpctl_sycl_program_interface.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,32 @@
3333
#ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
3434
#include <level_zero/zet_api.h> /* Level Zero headers */
3535
#include <CL/sycl/backend/level_zero.hpp>
36+
#include "../helper/include/dpctl_dynamic_lib_helper.h"
3637
#endif
3738

3839
using namespace cl::sycl;
3940

4041
namespace
4142
{
43+
#ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
44+
45+
#ifdef __linux__
46+
static const char * zeLoaderName = "libze_loader.so";
47+
static const int libLoadFlags = RTLD_NOLOAD | RTLD_NOW | RTLD_LOCAL;
48+
#else
49+
#error "Level Zero program compilation is unavailable for this platform"
50+
#endif
51+
52+
typedef ze_result_t (*zeModuleCreateFT)(ze_context_handle_t,
53+
ze_device_handle_t,
54+
const ze_module_desc_t *,
55+
ze_module_handle_t *,
56+
ze_module_build_log_handle_t *);
57+
58+
const char * zeModuleCreateFuncName = "zeModuleCreate";
59+
60+
#endif // #ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
61+
4262
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(context, DPCTLSyclContextRef)
4363
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(program, DPCTLSyclProgramRef)
4464
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(kernel, DPCTLSyclKernelRef)
@@ -90,6 +110,23 @@ createOpenCLInterOpProgram (const context &SyclCtx,
90110
}
91111

92112
#ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
113+
114+
zeModuleCreateFT getZeModuleCreateFn ()
115+
{
116+
static dpctl::DynamicLibHelper zeLib(zeLoaderName, libLoadFlags);
117+
if(!zeLib.opened()) {
118+
// TODO: handle error
119+
std::cerr << "The level zero loader dynamic library could not "
120+
"be opened.\n";
121+
return nullptr;
122+
}
123+
static auto stZeModuleCreateF = zeLib.getSymbol<zeModuleCreateFT>(
124+
zeModuleCreateFuncName
125+
);
126+
127+
return stZeModuleCreateF;
128+
}
129+
93130
__dpctl_give DPCTLSyclProgramRef
94131
createLevelZeroInterOpProgram (const context &SyclCtx,
95132
const void *IL,
@@ -99,8 +136,8 @@ createLevelZeroInterOpProgram (const context &SyclCtx,
99136
auto ZeCtx = SyclCtx.get_native<backend::level_zero>();
100137
auto SyclDevices = SyclCtx.get_devices();
101138
if(SyclDevices.size() > 1) {
102-
// We only support build to one device with Level Zero now.
103-
// TODO: log error
139+
std::cerr << "Level zero program can be created for only one device.\n";
140+
// TODO: handle error
104141
return nullptr;
105142
}
106143

@@ -119,8 +156,14 @@ createLevelZeroInterOpProgram (const context &SyclCtx,
119156

120157
auto ZeDevice = SyclDevices[0].get_native<backend::level_zero>();
121158
ze_module_handle_t ZeModule;
122-
auto ret = zeModuleCreate(ZeCtx, ZeDevice, &ZeModuleDesc, &ZeModule,
123-
nullptr);
159+
160+
auto stZeModuleCreateF = getZeModuleCreateFn();
161+
162+
if(!stZeModuleCreateF)
163+
return nullptr;
164+
165+
auto ret = stZeModuleCreateF(ZeCtx, ZeDevice, &ZeModuleDesc, &ZeModule,
166+
nullptr);
124167
if(ret != ZE_RESULT_SUCCESS) {
125168
// TODO: handle error
126169
return nullptr;
@@ -138,7 +181,8 @@ createLevelZeroInterOpProgram (const context &SyclCtx,
138181
return nullptr;
139182
}
140183
}
141-
#endif
184+
#endif /* #ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION */
185+
142186
} /* end of anonymous namespace */
143187

144188
__dpctl_give DPCTLSyclProgramRef
@@ -156,7 +200,7 @@ DPCTLProgram_CreateFromSpirv (__dpctl_keep const DPCTLSyclContextRef CtxRef,
156200
SyclCtx = unwrap(CtxRef);
157201
// get the backend type
158202
auto BE = SyclCtx->get_platform().get_backend();
159-
switch (BE)
203+
switch(BE)
160204
{
161205
case backend::opencl:
162206
Pref = createOpenCLInterOpProgram(*SyclCtx, IL, length, CompileOpts);

dpctl-capi/tests/test_sycl_program_interface.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,12 @@ struct TestDPCTLSyclProgramInterface : public ::testing::Test
127127
size_t spirvFileSize = 0;
128128
std::vector<char> spirvBuffer;
129129
size_t nOpenCLGpuQ = 0;
130-
#ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
131-
size_t nL0GpuQ = 0;
132-
#endif
133130

134131
TestDPCTLSyclProgramInterface () :
135132
spirvFile{"./multi_kernel.spv", std::ios::binary | std::ios::ate},
136133
spirvFileSize(std::filesystem::file_size("./multi_kernel.spv")),
137134
spirvBuffer(spirvFileSize),
138-
nOpenCLGpuQ(DPCTLQueueMgr_GetNumQueues(DPCTL_OPENCL, DPCTL_GPU)),
139-
nL0GpuQ(DPCTLQueueMgr_GetNumQueues(DPCTL_LEVEL_ZERO, DPCTL_GPU))
135+
nOpenCLGpuQ(DPCTLQueueMgr_GetNumQueues(DPCTL_OPENCL, DPCTL_GPU))
140136
{
141137
spirvFile.seekg(0, std::ios::beg);
142138
spirvFile.read(spirvBuffer.data(), spirvFileSize);
@@ -188,6 +184,7 @@ TEST_F (TestDPCTLSyclProgramInterface, CheckCreateFromSpirvOCL)
188184
#ifdef DPCTL_ENABLE_LO_PROGRAM_CREATION
189185
TEST_F (TestDPCTLSyclProgramInterface, CheckCreateFromSpirvL0)
190186
{
187+
auto nL0GpuQ = DPCTLQueueMgr_GetNumQueues(DPCTL_LEVEL_ZERO, DPCTL_GPU);
191188
if(!nL0GpuQ)
192189
GTEST_SKIP_("Skipping as no OpenCL GPU device found.\n");
193190

0 commit comments

Comments
 (0)