Skip to content

[SYCL] Implement sycl_ext_oneapi_kernel_compiler_spirv #12291

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 19 commits into from
Jan 18, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ This extension also depends on the following other SYCL extensions:

== Status

This is a proposed extension specification, intended to gather community
feedback.
Interfaces defined in this specification may not be implemented yet or may be
in a preliminary state.
The specification itself may also change in incompatible ways before it is
finalized.
*Shipping software products should not rely on APIs defined in this
specification.*
This is an experimental extension specification, intended to provide early
access to features and gather community feedback. Interfaces defined in
this specification are implemented in DPC++, but they are not finalized
and may change incompatibly in future versions of DPC++ without prior notice.
*Shipping software products should not rely on APIs defined in
this specification.*


== Overview
Expand Down
18 changes: 13 additions & 5 deletions sycl/include/sycl/kernel_bundle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <sycl/ext/oneapi/properties/property_value.hpp> // and log

#include <array> // for array
#include <cstddef> // for std::byte
#include <cstring> // for size_t, memcpy
#include <functional> // for function
#include <iterator> // for distance
Expand All @@ -46,7 +47,7 @@ auto get_native(const kernel_bundle<State> &Obj)
namespace detail {
class kernel_id_impl;
class kernel_impl;
}
} // namespace detail

template <typename KernelName> kernel_id get_kernel_id();

Expand Down Expand Up @@ -886,11 +887,18 @@ __SYCL_EXPORT bool is_source_kernel_bundle_supported(backend BE,
/////////////////////////
// syclex::create_kernel_bundle_from_source
/////////////////////////

__SYCL_EXPORT kernel_bundle<bundle_state::ext_oneapi_source>
create_kernel_bundle_from_source(const context &SyclContext,
source_language Language,
const std::string &Source);

#if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
__SYCL_EXPORT kernel_bundle<bundle_state::ext_oneapi_source>
create_kernel_bundle_from_source(
const context &SyclContext,
sycl::ext::oneapi::experimental::source_language Language,
const std::string &Source);
create_kernel_bundle_from_source(const context &SyclContext,
source_language Language,
const std::vector<std::byte> &Bytes);
Copy link
Contributor

@cperkinsintel cperkinsintel Jan 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gmlueck I definitely think creating kernel bundles from spirv binary ( .spv ) is the right thing.

But there is a tiny bit of a disconnect there, where we are creating "from source" and yet that source is .spv binary not .spt the textual human(*) readable representation of SPIR-V. Anyway, I'm not trying to make more work for anyone. Nor do I think there is any real demand for using .spt sources. But it does seem a bit funny.

(*) I guess .spt is "almost human" readable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that calling SPIR-V binary "source" is a bit of a misnomer, but all the APIs work out pretty well. We could easily add SPIR-V source support in the future by adding a new enumerator like source_language::spirv_source. However, I think there is no compelling reason to do that unless there is some request.

#endif

/////////////////////////
// syclex::build(source_kb) => exe_kb
Expand Down
2 changes: 1 addition & 1 deletion sycl/include/sycl/kernel_bundle_enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enum class bundle_state : char {

namespace ext::oneapi::experimental {

enum class source_language : int { opencl = 0 /* sycl , spir-v, cuda */ };
enum class source_language : int { opencl = 0, spirv = 1 /* sycl, cuda */ };

} // namespace ext::oneapi::experimental

Expand Down
39 changes: 29 additions & 10 deletions sycl/source/detail/kernel_bundle_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <memory>
#include <vector>
Expand Down Expand Up @@ -334,6 +335,14 @@ class kernel_bundle_impl {
: MContext(Context), MDevices(Context.get_devices()),
MState(bundle_state::ext_oneapi_source), Language(Lang), Source(Src) {}

// oneapi_ext_kernel_compiler
// construct from source bytes
kernel_bundle_impl(const context &Context, syclex::source_language Lang,
const std::vector<std::byte> &Bytes)
: MContext(Context), MDevices(Context.get_devices()),
MState(bundle_state::ext_oneapi_source), Language(Lang), Source(Bytes) {
}

// oneapi_ext_kernel_compiler
// interop constructor
kernel_bundle_impl(context Ctx, std::vector<device> Devs,
Expand All @@ -350,17 +359,27 @@ class kernel_bundle_impl {
std::string *LogPtr) {
assert(MState == bundle_state::ext_oneapi_source &&
"bundle_state::ext_oneapi_source required");
assert(Language == syclex::source_language::opencl &&
"TODO: add other Languages. Must be OpenCL");
if (Language != syclex::source_language::opencl)

const auto spirv = [&]() -> std::vector<uint8_t> {
if (Language == syclex::source_language::opencl) {
// if successful, the log is empty. if failed, throws an error with the
// compilation log.
const auto &SourceStr = std::get<std::string>(this->Source);
return syclex::detail::OpenCLC_to_SPIRV(SourceStr, BuildOptions,
LogPtr);
}
if (Language == syclex::source_language::spirv) {
const auto &SourceBytes =
std::get<std::vector<std::byte>>(this->Source);
std::vector<uint8_t> Result(SourceBytes.size());
std::transform(SourceBytes.cbegin(), SourceBytes.cend(), Result.begin(),
[](std::byte B) { return static_cast<uint8_t>(B); });
return Result;
}
throw sycl::exception(
make_error_code(errc::invalid),
"OpenCL C is the only supported language at this time");

// if successful, the log is empty. if failed, throws an error with the
// compilation log.
auto spirv =
syclex::detail::OpenCLC_to_SPIRV(this->Source, BuildOptions, LogPtr);
"OpenCL C and SPIR-V are the only supported languages at this time");
}();

// see also program_manager.cpp::createSpirvProgram()
using ContextImplPtr = std::shared_ptr<sycl::detail::context_impl>;
Expand Down Expand Up @@ -682,7 +701,7 @@ class kernel_bundle_impl {
bundle_state MState;
// ext_oneapi_kernel_compiler : Source, Languauge, KernelNames
const syclex::source_language Language = syclex::source_language::opencl;
const std::string Source;
const std::variant<std::string, std::vector<std::byte>> Source;
// only kernel_bundles created from source have KernelNames member.
std::vector<std::string> KernelNames;
};
Expand Down
1 change: 1 addition & 0 deletions sycl/source/feature_test.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ inline namespace _V1 {
#define SYCL_EXT_ONEAPI_GROUP_SORT 1
#define SYCL_EXT_ONEAPI_KERNEL_COMPILER 1
#define SYCL_EXT_ONEAPI_KERNEL_COMPILER_OPENCL 1
#define SYCL_EXT_ONEAPI_KERNEL_COMPILER_SPIRV 1
#define SYCL_EXT_ONEAPI_MAX_WORK_GROUP_QUERY 1
#define SYCL_EXT_ONEAPI_ND_RANGE_REDUCTIONS 1
#define SYCL_EXT_ONEAPI_DEFAULT_CONTEXT 1
Expand Down
29 changes: 25 additions & 4 deletions sycl/source/kernel_bundle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
#include <detail/kernel_id_impl.hpp>
#include <detail/program_manager/program_manager.hpp>

#include <cstddef>
#include <set>
#include <vector>

namespace sycl {
inline namespace _V1 {
Expand Down Expand Up @@ -368,12 +370,16 @@ using kernel_bundle_impl = sycl::detail::kernel_bundle_impl;
// syclex::is_source_kernel_bundle_supported
/////////////////////////
bool is_source_kernel_bundle_supported(backend BE, source_language Language) {
// at the moment, OpenCL is the only language supported
// and it's support is limited to the opencl and level_zero backends.
// Support is limited to the opencl and level_zero backends.
bool BE_Acceptable = (BE == sycl::backend::ext_oneapi_level_zero) ||
(BE == sycl::backend::opencl);
if ((Language == source_language::opencl) && BE_Acceptable) {
return detail::OpenCLC_Compilation_Available();
if (BE_Acceptable) {
// At the moment, OpenCL and SPIR-V are the only supported languages.
if (Language == source_language::opencl) {
return detail::OpenCLC_Compilation_Available();
} else if (Language == source_language::spirv) {
return true;
}
}

// otherwise
Expand All @@ -383,6 +389,7 @@ bool is_source_kernel_bundle_supported(backend BE, source_language Language) {
/////////////////////////
// syclex::create_kernel_bundle_from_source
/////////////////////////

source_kb create_kernel_bundle_from_source(const context &SyclContext,
source_language Language,
const std::string &Source) {
Expand All @@ -399,6 +406,20 @@ source_kb create_kernel_bundle_from_source(const context &SyclContext,
return sycl::detail::createSyclObjFromImpl<source_kb>(KBImpl);
}

source_kb
create_kernel_bundle_from_source(const context &SyclContext,
source_language Language,
const std::vector<std::byte> &Bytes) {
backend BE = SyclContext.get_backend();
if (!is_source_kernel_bundle_supported(BE, Language))
throw sycl::exception(make_error_code(errc::invalid),
"kernel_bundle creation from source not supported");

std::shared_ptr<kernel_bundle_impl> KBImpl =
std::make_shared<kernel_bundle_impl>(SyclContext, Language, Bytes);
return sycl::detail::createSyclObjFromImpl<source_kb>(KBImpl);
}

/////////////////////////
// syclex::detail::build_from_source(source_kb) => exe_kb
/////////////////////////
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading