Skip to content

Commit dc8bd7d

Browse files
committed
[SYCL] Add specialization constant support in SYCL runtime.
Based on https://github.com/codeplaysoftware/standards-proposals/blob/master/spec-constant/index.md 1. Define SYCL API (sycl/include/CL/sycl/experimental/spec_constant.hpp) 2. Add convenience C++ wrappers for PI device binary structures and refactor runtime to use the wrappers. Get rid of custom deleters for binary images. 3. Implement SYCL spec constant APIs in program an program manager. Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent 42dfab4 commit dc8bd7d

19 files changed

+979
-152
lines changed

sycl/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ add_custom_target( sycl-toolchain
210210
clang
211211
clang-offload-wrapper
212212
clang-offload-bundler
213-
file-table-tform
213+
file-table-tform
214214
llc
215215
llvm-ar
216216
llvm-foreach

sycl/include/CL/sycl/detail/os_util.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class OSUtil {
8080
/// single one at most.
8181
static constexpr OSModuleHandle ExeModuleHandle = -1;
8282

83+
/// Dummy module handle to designate non-existing module for a device binary
84+
/// image loaded from file e.g. via SYCL_USE_KERNEL_SPV env var.
85+
static constexpr OSModuleHandle DummyModuleHandle = -2;
86+
8387
#ifdef SYCL_RT_OS_WINDOWS
8488
static constexpr const char* DirSep = "\\";
8589
#else
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//==-- spec_constant_impl.hpp - SYCL RT model for specialization constants -==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
11+
#include <CL/sycl/detail/defines.hpp>
12+
13+
#include <iostream>
14+
15+
__SYCL_INLINE_NAMESPACE(cl) {
16+
namespace sycl {
17+
namespace detail {
18+
19+
// Represents a specialization constant in SYCL runtime.
20+
class spec_constant_impl {
21+
public:
22+
spec_constant_impl(unsigned int ID) : ID(ID), Size(0), Bytes{0} {}
23+
24+
spec_constant_impl(unsigned int ID, size_t Size, const void *Val) : ID(ID) {
25+
set(Size, Val);
26+
}
27+
28+
void set(size_t Size, const void *Val);
29+
30+
unsigned int getID() const { return ID; }
31+
size_t getSize() const { return Size; }
32+
const unsigned char *getValuePtr() const { return Bytes; }
33+
bool isSet() const { return Size != 0; }
34+
35+
private:
36+
unsigned int ID; // specialization constant's ID (equals to SPIRV ID)
37+
size_t Size; // size of its value
38+
// TODO invent more flexible approach to support values of arbitrary type:
39+
unsigned char Bytes[8]; // memory to hold the value bytes
40+
};
41+
42+
std::ostream &operator<<(std::ostream &Out, const spec_constant_impl &V);
43+
44+
} // namespace detail
45+
} // namespace sycl
46+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/detail/sycl_fe_intrins.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@
1212

1313
#ifdef __SYCL_DEVICE_ONLY__
1414

15-
// Returns a unique string identifying the template parameter type. Stable
16-
// across device compiler invocations.
17-
template <typename T> const char *__sycl_fe_getStableUniqueTypeName();
18-
1915
// Get the value of the specialization constant with given name.
2016
// Post-link tool traces the ID to a string literal it points to and assigns
2117
// integer ID.
22-
template <typename T> T __sycl_getSpecConstantValue(const char *ID);
18+
template <typename T>
19+
SYCL_EXTERNAL T __sycl_getSpecConstantValue(const char *ID);
2320

2421
#endif

sycl/include/CL/sycl/detail/util.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <CL/sycl/detail/defines.hpp>
1414

15+
#include <cstring>
1516
#include <mutex>
1617

1718
__SYCL_INLINE_NAMESPACE(cl) {
@@ -30,6 +31,34 @@ class Sync {
3031
std::mutex GlobalLock;
3132
};
3233

34+
// const char* key hash for STL maps
35+
struct HashCStr {
36+
size_t operator()(const char *S) const {
37+
constexpr size_t Prime = 31;
38+
size_t Res = 0;
39+
char Ch = 0;
40+
41+
for (; (Ch = *S); S++) {
42+
Res += Ch + (Prime * Res);
43+
}
44+
return Res;
45+
}
46+
};
47+
48+
// const char* key comparison for STL maps
49+
struct CmpCStr {
50+
bool operator()(const char *A, const char *B) const {
51+
return std::strcmp(A, B) == 0;
52+
}
53+
};
54+
55+
// Interface to iterate via C strings.
56+
class CStringIterator {
57+
public:
58+
// Get the next string. Returns next string's pointer or nullptr.
59+
virtual const char *next() = 0;
60+
};
61+
3362
} // namespace detail
3463
} // namespace sycl
3564
} // __SYCL_INLINE_NAMESPACE(cl)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//==----- spec_constant.hpp - SYCL public experimental API header file -----==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// Based on:
10+
// https://github.com/codeplaysoftware/standards-proposals/blob/master/spec-constant/index.md
11+
// TODO:
12+
// 1) implement the SPIRV interop part of the proposal
13+
// 2) support arbitrary spec constant type; only primitive types are
14+
// supported currently
15+
// 3) move to the new upcoming spec constant specification (then 1 above is not
16+
// needed)
17+
18+
#pragma once
19+
20+
#include <CL/sycl/detail/sycl_fe_intrins.hpp>
21+
#include <CL/sycl/exception.hpp>
22+
23+
namespace cl {
24+
namespace sycl {
25+
namespace experimental {
26+
27+
class spec_const_error : public compile_program_error {};
28+
29+
template <typename T, typename ID = T> class spec_constant {
30+
private:
31+
// Implementation defined constructor.
32+
#ifdef __SYCL_DEVICE_ONLY__
33+
spec_constant() {}
34+
#else
35+
spec_constant(T Cst) : Val(Cst) {}
36+
#endif
37+
#ifndef __SYCL_DEVICE_ONLY__
38+
T Val;
39+
#endif
40+
friend class cl::sycl::program;
41+
42+
public:
43+
T get() const { // explicit access.
44+
#ifdef __SYCL_DEVICE_ONLY__
45+
const char *TName = __unique_stable_name(ID);
46+
return __sycl_getSpecConstantValue<T>(TName);
47+
#else
48+
return Val;
49+
#endif // __SYCL_DEVICE_ONLY__
50+
}
51+
52+
operator T() const { // implicit conversion.
53+
return get();
54+
}
55+
};
56+
57+
} // namespace experimental
58+
} // namespace sycl
59+
} // namespace cl

sycl/include/CL/sycl/program.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <CL/sycl/context.hpp>
1212
#include <CL/sycl/detail/kernel_desc.hpp>
1313
#include <CL/sycl/detail/os_util.hpp>
14+
#include <CL/sycl/experimental/spec_constant.hpp>
1415
#include <CL/sycl/info/info_desc.hpp>
1516
#include <CL/sycl/kernel.hpp>
1617
#include <CL/sycl/stl.hpp>
@@ -293,6 +294,25 @@ class program {
293294
/// \return the current state of this SYCL program.
294295
program_state get_state() const;
295296

297+
/// Set the value of the specialization constant identified by the 'ID' type
298+
/// template parameter and return its instance.
299+
/// \param cst the specialization constant value
300+
/// \return a specialization constant instance corresponding to given type ID
301+
/// passed as a template parameter
302+
template <typename ID, typename T>
303+
experimental::spec_constant<T, ID> set_spec_constant(T Cst) {
304+
constexpr const char *Name = detail::SpecConstantInfo<ID>::getName();
305+
static_assert(std::is_integral<T>::value ||
306+
std::is_floating_point<T>::value,
307+
"unsupported specialization constant type");
308+
#ifdef __SYCL_DEVICE_ONLY__
309+
return experimental::spec_constant<T, ID>();
310+
#else
311+
set_spec_constant_impl(Name, &Cst, sizeof(T));
312+
return experimental::spec_constant<T, ID>(Cst);
313+
#endif // __SYCL_DEVICE_ONLY__
314+
}
315+
296316
private:
297317
program(shared_ptr_class<detail::program_impl> impl);
298318

@@ -330,6 +350,8 @@ class program {
330350
string_class buildOptions,
331351
detail::OSModuleHandle M);
332352

353+
void set_spec_constant_impl(const char *Name, void *Data, size_t Size);
354+
333355
shared_ptr_class<detail::program_impl> impl;
334356

335357
template <class Obj>

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ set(SYCL_SOURCES
103103
"detail/scheduler/scheduler.cpp"
104104
"detail/scheduler/graph_processor.cpp"
105105
"detail/scheduler/graph_builder.cpp"
106+
"detail/spec_constant_impl.cpp"
106107
"detail/sycl_mem_obj_t.cpp"
107108
"detail/usm/clusm.cpp"
108109
"detail/usm/usm_dispatch.cpp"

sycl/source/detail/os_util.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct ModuleInfo {
5757
};
5858

5959
constexpr OSModuleHandle OSUtil::ExeModuleHandle;
60+
constexpr OSModuleHandle OSUtil::DummyModuleHandle;
6061

6162
static int callback(struct dl_phdr_info *Info, size_t Size, void *Data) {
6263
auto Base = reinterpret_cast<unsigned char *>(Info->dlpi_addr);

sycl/source/detail/program_impl.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include <CL/sycl/detail/common.hpp>
1010
#include <CL/sycl/detail/kernel_desc.hpp>
11+
#include <CL/sycl/detail/pi.h>
12+
#include <CL/sycl/detail/spec_constant_impl.hpp>
1113
#include <CL/sycl/kernel.hpp>
1214
#include <detail/program_impl.hpp>
1315

@@ -311,6 +313,7 @@ void program_impl::compile(const string_class &Options) {
311313
check_device_feature_support<info::device::is_compiler_available>(MDevices);
312314
vector_class<RT::PiDevice> Devices(get_pi_devices());
313315
const detail::plugin &Plugin = getPlugin();
316+
ProgramManager::getInstance().flushSpecConstants(MProgram, *MContext);
314317
RT::PiResult Err = Plugin.call_nocheck<PiApiKind::piProgramCompile>(
315318
MProgram, Devices.size(), Devices.data(), Options.c_str(), 0, nullptr,
316319
nullptr, nullptr, nullptr);
@@ -329,6 +332,7 @@ void program_impl::build(const string_class &Options) {
329332
check_device_feature_support<info::device::is_compiler_available>(MDevices);
330333
vector_class<RT::PiDevice> Devices(get_pi_devices());
331334
const detail::plugin &Plugin = getPlugin();
335+
ProgramManager::getInstance().flushSpecConstants(MProgram, *MContext);
332336
RT::PiResult Err = Plugin.call_nocheck<PiApiKind::piProgramBuild>(
333337
MProgram, Devices.size(), Devices.data(), Options.c_str(), nullptr,
334338
nullptr);
@@ -417,7 +421,8 @@ void program_impl::create_pi_program_with_kernel_name(
417421
OSModuleHandle Module, const string_class &KernelName) {
418422
assert(!MProgram && "This program already has an encapsulated PI program");
419423
ProgramManager &PM = ProgramManager::getInstance();
420-
DeviceImage &Img = PM.getDeviceImage(Module, KernelName, get_context());
424+
RTDeviceBinaryImage &Img =
425+
PM.getDeviceImage(Module, KernelName, get_context());
421426
MProgram = PM.createPIProgram(Img, get_context());
422427
}
423428

@@ -444,6 +449,13 @@ vector_class<device> program_impl::get_info<info::program::devices>() const {
444449
return get_devices();
445450
}
446451

452+
void program_impl::set_spec_constant_impl(const char *Name, const void *ValAddr,
453+
size_t ValSize) {
454+
spec_constant_impl &SC =
455+
ProgramManager::getInstance().resolveSpecConstant(this, Name);
456+
SC.set(ValSize, ValAddr);
457+
}
458+
447459
} // namespace detail
448460
} // namespace sycl
449461
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/program_impl.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,16 @@ class program_impl {
293293
/// \return the current state of this SYCL program.
294294
program_state get_state() const { return MState; }
295295

296+
void set_spec_constant_impl(const char *Name, const void *ValAddr,
297+
size_t ValSize);
298+
299+
/// Returns the OS module handle this program belongs to. A program belongs to
300+
/// an OS module if it was built from device image(s) belonging to that
301+
/// module.
302+
/// TODO Some programs can be linked from images belonging to different
303+
/// modules. May need a special fake handle for the resulting program.
304+
OSModuleHandle getOSModuleHandle() const { return MProgramModuleHandle; }
305+
296306
private:
297307
// Deligating Constructor used in Implementation.
298308
program_impl(ContextImplPtr Context, program_interop_handle_t InteropProgram,

0 commit comments

Comments
 (0)