33 inline namespace _V1 {
39 Devices.begin(), Devices.end(), [&Context](
const device &Dev) {
40 return getSyclObjImpl(Context)->isDeviceValid(getSyclObjImpl(Dev));
47 [&Aspect](
const device &Dev) { return Dev.has(Aspect); });
50 namespace syclex = sycl::ext::oneapi::experimental;
59 using SpecConstMapT = std::map<std::string, std::vector<unsigned char>>;
62 const bool AllDevicesInTheContext =
64 if (MDevices.empty() || !AllDevicesInTheContext)
67 "Not all devices are associated with the context or "
68 "vector of devices is empty");
73 "Not all devices have aspect::online_compiler");
78 "Not all devices have aspect::online_linker");
83 : MContext(
std::move(Ctx)), MDevices(
std::move(Devs)), MState(State) {
85 common_ctor_checks(State);
88 MContext, MDevices, State);
93 : MContext(Ctx), MDevices(Devs), MState(
bundle_state::executable) {
97 "Not all devices are associated with the context or "
98 "vector of devices is empty");
106 MDeviceImages.push_back(DevImage);
116 MState(TargetState) {
118 MSpecConstValues =
getSyclObjImpl(InputBundle)->get_spec_const_map_ref();
120 const std::vector<device> &InputBundleDevices =
122 const bool AllDevsAssociatedWithInputBundle =
124 [&InputBundleDevices](
const device &Dev) {
125 return InputBundleDevices.end() !=
126 std::find(InputBundleDevices.begin(),
127 InputBundleDevices.end(), Dev);
129 if (MDevices.empty() || !AllDevsAssociatedWithInputBundle)
132 "Not all devices are in the set of associated "
133 "devices for input bundle or vector of devices is empty");
138 MDevices.begin(), MDevices.end(),
139 [&DeviceImage](
const device &Dev) {
140 return getSyclObjImpl(DeviceImage)->compatible_with_device(Dev);
144 switch (TargetState) {
147 DeviceImage, MDevices, PropList));
151 DeviceImage, MDevices, PropList));
156 "Internal error. The target state should not be input "
157 "or ext_oneapi_source");
169 if (MDevices.empty())
171 "Vector of devices is empty");
173 if (ObjectBundles.empty())
176 MContext = ObjectBundles[0].get_context();
177 for (
size_t I = 1; I < ObjectBundles.size(); ++I) {
181 "Not all input bundles have the same associated context");
186 const bool AllDevsAssociatedWithInputBundles =
std::all_of(
187 MDevices.begin(), MDevices.end(), [&ObjectBundles](
const device &Dev) {
190 ObjectBundles.begin(), ObjectBundles.end(),
191 [&Dev](const kernel_bundle<bundle_state::object> &KernelBundle) {
192 const std::vector<device> &BundleDevices =
193 getSyclObjImpl(KernelBundle)->get_devices();
194 return BundleDevices.end() != std::find(BundleDevices.begin(),
199 if (!AllDevsAssociatedWithInputBundles)
201 "Not all devices are in the set of associated "
202 "devices for input bundles");
220 [&DeviceImage](
const device &Dev) {
221 return getSyclObjImpl(DeviceImage)
222 ->compatible_with_device(Dev);
226 std::vector<device_image_plain> LinkedResults =
229 MDeviceImages.insert(MDeviceImages.end(), LinkedResults.begin(),
230 LinkedResults.end());
236 for (
const std::pair<
const std::string, std::vector<unsigned char>>
237 &SpecConst : BundlePtr->MSpecConstValues) {
238 MSpecConstValues[SpecConst.first] = SpecConst.second;
244 const std::vector<kernel_id> &KernelIDs,
246 : MContext(
std::move(Ctx)), MDevices(
std::move(Devs)), MState(State) {
248 common_ctor_checks(State);
251 MContext, MDevices, KernelIDs, State);
256 : MContext(
std::move(Ctx)), MDevices(
std::move(Devs)), MState(State) {
258 common_ctor_checks(State);
261 MContext, MDevices, Selector, State);
271 MContext = Bundles[0]->MContext;
272 MDevices = Bundles[0]->MDevices;
273 for (
size_t I = 1; I < Bundles.size(); ++I) {
274 if (Bundles[I]->MContext != MContext)
277 "Not all input bundles have the same associated context.");
278 if (Bundles[I]->MDevices != MDevices)
281 "Not all input bundles have the same set of associated devices.");
286 MDeviceImages.insert(MDeviceImages.end(), Bundle->MDeviceImages.begin(),
287 Bundle->MDeviceImages.end());
290 std::sort(MDeviceImages.begin(), MDeviceImages.end(),
297 const std::map<std::string,
298 std::vector<device_image_impl::SpecConstDescT>>
299 &SpecConsts = ImgImpl->get_spec_const_data_ref();
300 const std::vector<unsigned char> &Blob =
301 ImgImpl->get_spec_const_blob_ref();
302 for (
const std::pair<
const std::string,
303 std::vector<device_image_impl::SpecConstDescT>>
304 &SpecConst : SpecConsts) {
305 if (SpecConst.second.front().IsSet)
306 set_specialization_constant_raw_value(
307 SpecConst.first.c_str(),
308 Blob.data() + SpecConst.second.front().BlobOffset,
309 SpecConst.second.back().CompositeOffset +
310 SpecConst.second.back().Size);
317 const auto DevImgIt =
318 std::unique(MDeviceImages.begin(), MDeviceImages.end());
321 MDeviceImages.erase(DevImgIt, MDeviceImages.end());
324 for (
const std::pair<
const std::string, std::vector<unsigned char>>
325 &SpecConst : Bundle->MSpecConstValues) {
326 set_specialization_constant_raw_value(SpecConst.first.c_str(),
327 SpecConst.second.data(),
328 SpecConst.second.size());
334 std::vector<std::pair<std::string , std::string >>;
339 : MContext(Context), MDevices(Context.get_devices()),
341 IncludePairs(IncludePairsVec) {}
346 const std::vector<std::byte> &Bytes)
347 : MContext(Context), MDevices(Context.get_devices()),
355 std::vector<std::string> KNames,
359 KernelNames = KNames;
365 char EncounteredQuote =
'\0';
366 auto Start = std::find_if(str.begin(), str.end(), [&](
char c) {
367 if (!EncounteredQuote && (c ==
'\'' || c ==
'"')) {
368 EncounteredQuote = c;
371 return !std::isspace(c);
373 auto End = std::find_if(str.rbegin(), str.rend(), [&](
char c) {
374 if (c == EncounteredQuote) {
375 EncounteredQuote =
'\0';
378 return !std::isspace(c);
380 if (Start != std::end(str) && End != std::begin(str) && Start < End) {
381 return std::string(Start, End);
388 std::stringstream SS;
390 auto Where = Option.find(
"-Xs");
391 if (Where != std::string::npos) {
393 std::string Flags = Option.substr(Where);
394 SS << trimXsFlags(Flags) <<
" ";
400 std::shared_ptr<kernel_bundle_impl>
405 assert(MState == bundle_state::ext_oneapi_source &&
406 "bundle_state::ext_oneapi_source required");
408 using ContextImplPtr = std::shared_ptr<sycl::detail::context_impl>;
410 const PluginPtr &Plugin = ContextImpl->getPlugin();
412 std::vector<pi::PiDevice> DeviceVec;
413 DeviceVec.reserve(Devices.size());
414 for (
const auto &SyclDev : Devices) {
416 DeviceVec.push_back(Dev);
419 const auto spirv = [&]() -> std::vector<uint8_t> {
420 if (Language == syclex::source_language::opencl) {
423 const auto &SourceStr = std::get<std::string>(this->Source);
424 std::vector<uint32_t> IPVersionVec(Devices.size());
425 std::transform(DeviceVec.begin(), DeviceVec.end(), IPVersionVec.begin(),
427 uint32_t ipVersion = 0;
428 Plugin->call<PiApiKind::piDeviceGetInfo>(
429 d, PI_EXT_ONEAPI_DEVICE_INFO_IP_VERSION,
430 sizeof(uint32_t), &ipVersion, nullptr);
436 if (Language == syclex::source_language::spirv) {
437 const auto &SourceBytes =
438 std::get<std::vector<std::byte>>(this->Source);
439 std::vector<uint8_t> Result(SourceBytes.size());
440 std::transform(SourceBytes.cbegin(), SourceBytes.cend(), Result.begin(),
441 [](
std::byte B) { return static_cast<uint8_t>(B); });
444 if (Language == syclex::source_language::sycl) {
445 const auto &SourceStr = std::get<std::string>(this->Source);
452 "OpenCL C and SPIR-V are the only supported languages at this time");
457 ContextImpl->getHandleRef(), spirv.data(), spirv.size(), &
PiProgram);
462 PiProgram, DeviceVec.size(), DeviceVec.data(), XsFlags.c_str(),
nullptr,
472 size_t KernelNamesSize;
477 std::string KernelNamesStr(KernelNamesSize,
' ');
480 &KernelNamesStr[0],
nullptr);
481 std::vector<std::string> KernelNames =
485 auto KernelIDs = std::make_shared<std::vector<kernel_id>>();
486 auto DevImgImpl = std::make_shared<device_image_impl>(
487 nullptr, MContext, MDevices, bundle_state::executable, KernelIDs,
490 return std::make_shared<kernel_bundle_impl>(MContext, MDevices, DevImg,
491 KernelNames, Language);
497 if (Lang != syclex::source_language::sycl)
500 bool isMangled = Name.find(
"__sycl_kernel_") != std::string::npos;
501 return isMangled ? Name :
"__sycl_kernel_" + Name;
505 auto it = std::find(KernelNames.begin(), KernelNames.end(),
506 adjust_kernel_name(Name, Language));
507 return it != KernelNames.end();
512 const std::shared_ptr<kernel_bundle_impl> &Self) {
513 if (KernelNames.empty())
515 "'ext_oneapi_get_kernel' is only available in "
516 "kernel_bundles successfully built from "
517 "kernel_bundle<bundle_state:ext_oneapi_source>.");
519 std::string AdjustedName = adjust_kernel_name(Name, Language);
520 if (!ext_oneapi_has_kernel(Name))
522 "kernel '" + AdjustedName +
523 "' not found in kernel_bundle");
525 assert(MDeviceImages.size() > 0);
526 const std::shared_ptr<detail::device_image_impl> &DeviceImageImpl =
530 const PluginPtr &Plugin = ContextImpl->getPlugin();
536 std::shared_ptr<kernel_impl> KernelImpl = std::make_shared<kernel_impl>(
539 return detail::createSyclObjFromImpl<kernel>(KernelImpl);
545 return MContext.get_platform().get_backend();
555 std::vector<kernel_id> Result;
557 const std::vector<kernel_id> &KernelIDs =
560 Result.insert(Result.end(), KernelIDs.begin(), KernelIDs.end());
564 auto NewIt = std::unique(Result.begin(), Result.end(),
EqualByNameComp{});
565 Result.erase(NewIt, Result.end());
572 const std::shared_ptr<detail::kernel_bundle_impl> &Self)
const {
573 using ImageImpl = std::shared_ptr<detail::device_image_impl>;
575 ImageImpl SelectedImage =
nullptr;
577 ImageImpl ImageWithReplacedSpecConsts =
nullptr;
580 ImageImpl OriginalImage =
nullptr;
583 bool SpecConstsSet =
false;
584 for (
auto &DeviceImage : MDeviceImages) {
585 if (!DeviceImage.has_kernel(KernelID))
589 SpecConstsSet |= DeviceImageImpl->is_any_specialization_constant_set();
593 (DeviceImageImpl->specialization_constants_replaced_with_default()
594 ? ImageWithReplacedSpecConsts
595 : OriginalImage) = DeviceImageImpl;
602 SelectedImage = OriginalImage;
604 SelectedImage->all_specialization_constant_native())
613 if (ImageWithReplacedSpecConsts &&
614 !ImageWithReplacedSpecConsts->all_specialization_constant_native())
615 SelectedImage = ImageWithReplacedSpecConsts;
618 SelectedImage = OriginalImage;
624 "The kernel bundle does not contain the kernel "
625 "identified by kernelId.");
627 auto [
Kernel, CacheMutex, ArgMask] =
628 detail::ProgramManager::getInstance().getOrCreateKernel(
630 SelectedImage->get_program_ref());
632 std::shared_ptr<kernel_impl> KernelImpl = std::make_shared<kernel_impl>(
634 SelectedImage->get_program_ref(), CacheMutex);
636 return detail::createSyclObjFromImpl<kernel>(KernelImpl);
640 return std::any_of(MDeviceImages.begin(), MDeviceImages.end(),
642 return DeviceImage.has_kernel(KernelID);
648 MDeviceImages.begin(), MDeviceImages.end(),
650 return DeviceImage.has_kernel(KernelID, Dev);
656 MDeviceImages.begin(), MDeviceImages.end(),
658 return getSyclObjImpl(DeviceImage)->has_specialization_constants();
663 return contains_specialization_constants() &&
664 std::all_of(MDeviceImages.begin(), MDeviceImages.end(),
666 return getSyclObjImpl(DeviceImage)
667 ->all_specialization_constant_native();
672 return std::any_of(MDeviceImages.begin(), MDeviceImages.end(),
674 return getSyclObjImpl(DeviceImage)
675 ->has_specialization_constant(SpecName);
682 if (has_specialization_constant(SpecName))
685 ->set_specialization_constant_raw_value(SpecName, Value);
687 std::vector<unsigned char> &Val = MSpecConstValues[std::string{SpecName}];
689 std::memcpy(Val.data(), Value, Size);
696 if (
getSyclObjImpl(DeviceImage)->has_specialization_constant(SpecName)) {
698 ->get_specialization_constant_raw_value(SpecName, ValueRet);
704 if (MSpecConstValues.count(std::string{SpecName}) != 0) {
705 const std::vector<unsigned char> &Val =
706 MSpecConstValues.at(std::string{SpecName});
707 auto *Dest =
static_cast<unsigned char *
>(ValueRet);
708 std::uninitialized_copy(Val.begin(), Val.end(), Dest);
713 "get_specialization_constant_raw_value called for missing constant");
718 std::any_of(MDeviceImages.begin(), MDeviceImages.end(),
720 return getSyclObjImpl(DeviceImage)
721 ->is_specialization_constant_set(SpecName);
723 return SetInDevImg || MSpecConstValues.count(std::string{SpecName}) != 0;
729 return MDeviceImages.data() + MDeviceImages.size();
737 return MSpecConstValues;
744 if (has_kernel(KernelID, Dev))
749 std::vector<device_image_plain> NewDevImgs =
750 detail::ProgramManager::getInstance().getSYCLDeviceImages(
751 MContext, {Dev}, {KernelID}, BundleState);
754 if (NewDevImgs.empty())
759 for (
auto SpecConst : MSpecConstValues)
761 SpecConst.first.c_str(), SpecConst.second.data());
764 MDeviceImages.insert(MDeviceImages.end(), NewDevImgs.begin(),
771 std::vector<device> MDevices;
772 std::vector<device_image_plain> MDeviceImages;
775 SpecConstMapT MSpecConstValues;
776 bool MIsInterop =
false;
782 const std::variant<std::string, std::vector<std::byte>> Source;
784 std::vector<std::string> KernelNames;
The context class represents a SYCL context on which kernel functions may be executed.
std::vector< device_image_plain > getSYCLDeviceImages(const context &Ctx, const std::vector< device > &Devs, bundle_state State)
static ProgramManager & getInstance()
std::vector< device_image_plain > link(const device_image_plain &DeviceImages, const std::vector< device > &Devs, const property_list &PropList)
The class is an impl counterpart of the sycl::kernel_bundle.
bool empty() const noexcept
bool has_kernel(const kernel_id &KernelID) const noexcept
const SpecConstMapT & get_spec_const_map_ref() const noexcept
std::string adjust_kernel_name(const std::string &Name, syclex::source_language Lang)
kernel_bundle_impl(const std::vector< kernel_bundle< bundle_state::object >> &ObjectBundles, std::vector< device > Devs, const property_list &PropList)
kernel_bundle_impl(context Ctx, std::vector< device > Devs)
kernel_bundle_impl(const context &Context, syclex::source_language Lang, const std::string &Src, include_pairs_t IncludePairsVec)
bool add_kernel(const kernel_id &KernelID, const device &Dev)
kernel ext_oneapi_get_kernel(const std::string &Name, const std::shared_ptr< kernel_bundle_impl > &Self)
size_t size() const noexcept
kernel_bundle_impl(context Ctx, std::vector< device > Devs, device_image_plain &DevImage)
bundle_state get_bundle_state() const
const device_image_plain * end() const
kernel_bundle_impl(const context &Context, syclex::source_language Lang, const std::vector< std::byte > &Bytes)
const std::vector< device > & get_devices() const noexcept
void set_specialization_constant_raw_value(const char *SpecName, const void *Value, size_t Size) noexcept
context get_context() const noexcept
bool contains_specialization_constants() const noexcept
std::vector< kernel_id > get_kernel_ids() const
std::vector< std::pair< std::string, std::string > > include_pairs_t
bool is_specialization_constant_set(const char *SpecName) const noexcept
bool native_specialization_constant() const noexcept
std::string extractXsFlags(const std::vector< std::string > &BuildOptions)
kernel_bundle_impl(context Ctx, std::vector< device > Devs, const std::vector< kernel_id > &KernelIDs, bundle_state State)
kernel_bundle_impl(const kernel_bundle< bundle_state::input > &InputBundle, std::vector< device > Devs, const property_list &PropList, bundle_state TargetState)
const device_image_plain * begin() const
backend get_backend() const noexcept
kernel_bundle_impl(context Ctx, std::vector< device > Devs, bundle_state State)
kernel_bundle_impl(context Ctx, std::vector< device > Devs, device_image_plain &DevImage, std::vector< std::string > KNames, syclex::source_language Lang)
void get_specialization_constant_raw_value(const char *SpecName, void *ValueRet) const noexcept
bool has_specialization_constant(const char *SpecName) const noexcept
std::shared_ptr< kernel_bundle_impl > build_from_source(const std::vector< device > Devices, const std::vector< std::string > &BuildOptions, std::string *LogPtr, const std::vector< std::string > &RegisteredKernelNames)
bool ext_oneapi_has_kernel(const std::string &Name)
bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept
std::string trimXsFlags(std::string &str)
kernel get_kernel(const kernel_id &KernelID, const std::shared_ptr< detail::kernel_bundle_impl > &Self) const
kernel_bundle_impl(context Ctx, std::vector< device > Devs, const DevImgSelectorImpl &Selector, bundle_state State)
kernel_bundle_impl(const std::vector< detail::KernelBundleImplPtr > &Bundles, bundle_state State)
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
The kernel_bundle class represents collection of device images in a particular state.
Objects of the class identify kernel is some kernel_bundle related APIs.
const char * get_name() const noexcept
Provides an abstraction of a SYCL kernel.
Objects of the property_list class are containers for the SYCL properties.
std::shared_ptr< device_image_impl > DeviceImageImplPtr
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
static bool checkAllDevicesAreInContext(const std::vector< device > &Devices, const context &Context)
std::function< bool(const detail::DeviceImageImplPtr &DevImgImpl)> DevImgSelectorImpl
static bool checkAllDevicesHaveAspect(const std::vector< device > &Devices, aspect Aspect)
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
std::vector< std::string > split_string(std::string_view str, char delimeter)
std::shared_ptr< plugin > PluginPtr
std::shared_ptr< detail::kernel_bundle_impl > KernelBundleImplPtr
Function for_each(Group g, Ptr first, Ptr last, Function f)
spirv_vec_t OpenCLC_to_SPIRV(const std::string &Source, const std::vector< uint32_t > &IPVersionVec, const std::vector< std::string > &UserArgs, std::string *LogPtr)
std::vector< std::pair< std::string, std::string > > include_pairs_t
spirv_vec_t SYCL_to_SPIRV(const std::string &SYCLSource, include_pairs_t IncludePairs, const std::vector< std::string > &UserArgs, std::string *LogPtr, const std::vector< std::string > &RegisteredKernelNames)
kernel_bundle< bundle_state::executable > build(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList={})
kernel_bundle< bundle_state::object > compile(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList={})
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
pi_result piKernelCreate(pi_program program, const char *kernel_name, pi_kernel *ret_kernel)
pi_result piProgramGetInfo(pi_program program, pi_program_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
pi_result piProgramBuild(pi_program program, pi_uint32 num_devices, const pi_device *device_list, const char *options, void(*pfn_notify)(pi_program program, void *user_data), void *user_data)
pi_result piProgramCreate(pi_context context, const void *il, size_t length, pi_program *res_program)
@ PI_PROGRAM_INFO_KERNEL_NAMES
@ PI_PROGRAM_INFO_NUM_KERNELS
bool any_of(const simd_mask< _Tp, _Abi > &) noexcept
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept
_Abi const simd< _Tp, _Abi > & noexcept
bool none_of(const simd_mask< _Tp, _Abi > &) noexcept