-
Notifications
You must be signed in to change notification settings - Fork 797
[SYCL][ESIMD][EMU] ESIMD_CPU Kernel launch and ESIMD_EMU backend loading #4020
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
Changes from 33 commits
ee6e9e8
6b15320
3249056
7b163d6
0151dc7
7533a83
c96efe1
1266ceb
986a4f8
c14a755
33c3645
2a9e789
49bc656
1fd05a9
69d1cfb
94cb161
0b87d06
80d4c5e
b9f9663
686a2eb
7d1e481
8044e82
a586d1e
3671aad
1afc4dc
37a0e78
3710d07
6a41df5
bb6c3a0
b698f1e
f183ec2
4543b8f
21f11fe
30d738f
76771f4
c042ae7
ceb309d
b073a4e
be26fc0
d4846bf
7e65a1b
2ef648b
41490ea
9b57175
c7fad03
71b7a8f
06f132c
4d96d4b
e45087b
c1e6f9c
6985a64
8ee0bd8
2bf84de
b85ba9f
7a3e968
270763f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -551,6 +551,152 @@ class __SYCL_EXPORT handler { | |
} | ||
} | ||
|
||
/* The kernel passed to StoreLambda can take an id, an item or an nd_item as | ||
* its argument. Since esimd plugin directly invokes the kernel (doesn’t use | ||
* piKernelSetArg), the kernel argument type must be known to the plugin. | ||
* However, passing kernel argument type to the plugin requires changing ABI | ||
* in HostKernel class. To overcome this problem, helpers below wrap the | ||
* “original” kernel with a functor that always takes an nd_item as argument. | ||
* A functor is used instead of a lambda because extractArgsAndReqsFromLambda | ||
* needs access to the “original” kernel and keeps references to its internal | ||
* data, i.e. the kernel passed as argument cannot be local in scope. The | ||
* functor itself is again encapsulated in a std::function since functor’s | ||
* type is unknown to the plugin. | ||
*/ | ||
|
||
// For 'void' kernel argument | ||
template <class KernelType, class NormalizedKernelType, typename KernelName> | ||
KernelType *ResetHostKernelHelper(const KernelType &KernelFunc) { | ||
NormalizedKernelType NormalizedKernel(KernelFunc); | ||
auto NormalizedKernelFunc = std::function<void(void)>(NormalizedKernel); | ||
auto HostKernelPtr = | ||
new detail::HostKernel<decltype(NormalizedKernelFunc), void, 0, | ||
KernelName>(NormalizedKernelFunc); | ||
MHostKernel.reset(HostKernelPtr); | ||
return &HostKernelPtr->MKernel.template target<NormalizedKernelType>() | ||
->MKernelFunc; | ||
} | ||
|
||
// For non-'void' kernel argument - id, item w/wo offset, nd_item | ||
template <class KernelType, class NormalizedKernelType, int Dims, | ||
typename KernelName> | ||
KernelType *ResetHostKernelHelper(const KernelType &KernelFunc) { | ||
NormalizedKernelType NormalizedKernel(KernelFunc); | ||
auto NormalizedKernelFunc = | ||
std::function<void(const sycl::nd_item<Dims> &)>(NormalizedKernel); | ||
auto HostKernelPtr = | ||
new detail::HostKernel<decltype(NormalizedKernelFunc), | ||
sycl::nd_item<Dims>, Dims, KernelName>( | ||
NormalizedKernelFunc); | ||
MHostKernel.reset(HostKernelPtr); | ||
return &HostKernelPtr->MKernel.template target<NormalizedKernelType>() | ||
->MKernelFunc; | ||
} | ||
|
||
// For 'void' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, void>::value, KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
static_assert(Dims == 0, "Dimension of 'void' argument must be zero"); | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(void) { detail::runKernelWithoutArg(MKernelFunc); } | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
// For 'sycl::id<Dims>' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, sycl::id<Dims>>::value, | ||
KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(const nd_item<Dims> &Arg) { | ||
detail::runKernelWithArg(MKernelFunc, Arg.get_global_id()); | ||
} | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, Dims, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
// For 'sycl::nd_item<Dims>' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, sycl::nd_item<Dims>>::value, | ||
KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(const nd_item<Dims> &Arg) { | ||
detail::runKernelWithArg(MKernelFunc, Arg); | ||
} | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, Dims, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
// For 'sycl::item<Dims, without_offset>' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, sycl::item<Dims, false>>::value, | ||
KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(const nd_item<Dims> &Arg) { | ||
sycl::item<Dims, false> Item = detail::Builder::createItem<Dims, false>( | ||
Arg.get_global_range(), Arg.get_global_id()); | ||
detail::runKernelWithArg(MKernelFunc, Item); | ||
} | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, Dims, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
// For 'sycl::item<Dims, with_offset>' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, sycl::item<Dims, true>>::value, | ||
KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(const nd_item<Dims> &Arg) { | ||
sycl::item<Dims, true> Item = detail::Builder::createItem<Dims, true>( | ||
Arg.get_global_range(), Arg.get_global_id(), Arg.get_offset()); | ||
detail::runKernelWithArg(MKernelFunc, Item); | ||
} | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, Dims, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
// For 'sycl::group<Dims>' kernel argument | ||
template <class KernelType, typename ArgT, int Dims, typename KernelName> | ||
typename std::enable_if<std::is_same<ArgT, sycl::group<Dims>>::value, | ||
KernelType *>::type | ||
ResetHostKernel(const KernelType &KernelFunc) { | ||
struct NormalizedKernelType { | ||
KernelType MKernelFunc; | ||
NormalizedKernelType(const KernelType &KernelFunc) | ||
: MKernelFunc(KernelFunc) {} | ||
void operator()(const nd_item<Dims> &Arg) { | ||
detail::runKernelWithArg(MKernelFunc, Arg.get_group()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This version is supposed to be used with parallel_for_workgroup, which is not supported for ESIMD. So I'd make operator() just throw, and comment out There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following tests could fail without this change even if esimd_cpu build is disable by default.I applied this change because of them. https://github.com/intel/llvm-test-suite/blob/intel/SYCL/Basic/stream/stream.cpp There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tests containing parallel_for_work_group should not be run with ESIMD, as they will fail. You may exclude those tests for ESIMD_CPU_EMU. @vladimirlaz, can we create a lit feature for ESIMD CPU EMU plugin similar to opencl and level zero? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll revert changes related to this 'group' argument support after a lit feature for ESIMD CPU Emulation plug-in is created. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Am I right here? Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vladimirlaz / @kbobrovs , are we going to create a lit feature for ESIMD_CPU emulation for this type of exclusion? And, how did tests with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would like to highlight that on-device tests (the tests which actually executed on target BE) have been removed from the intel/llvm repo to intel/llvm-test-suite (see #4393). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vladimirlaz, the tests I mentioned above are already in intel/llvm-test-suite. You can see in their URLs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dongkyunahn-intel you can create LIT feature esimd_cpu and use it for the tests (like @kbobrovs suggested). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vladimirlaz , what file should I update for creating a LIT feature? |
||
} | ||
}; | ||
return ResetHostKernelHelper<KernelType, struct NormalizedKernelType, Dims, | ||
KernelName>(KernelFunc); | ||
} | ||
|
||
/// Stores lambda to the template-free object | ||
/// | ||
/// Also initializes kernel name, list of arguments and requirements using | ||
|
@@ -568,18 +714,19 @@ class __SYCL_EXPORT handler { | |
"kernel_handler is not yet supported by host device.", | ||
PI_INVALID_OPERATION); | ||
} | ||
MHostKernel.reset( | ||
new detail::HostKernel<KernelType, LambdaArgType, Dims, KernelName>( | ||
KernelFunc)); | ||
KernelType *KernelPtr = | ||
ResetHostKernel<KernelType, LambdaArgType, Dims, KernelName>( | ||
KernelFunc); | ||
|
||
using KI = sycl::detail::KernelInfo<KernelName>; | ||
// Empty name indicates that the compilation happens without integration | ||
// header, so don't perform things that require it. | ||
if (KI::getName() != nullptr && KI::getName()[0] != '\0') { | ||
// TODO support ESIMD in no-integration-header case too. | ||
MArgs.clear(); | ||
extractArgsAndReqsFromLambda(MHostKernel->getPtr(), KI::getNumParams(), | ||
&KI::getParamDesc(0), KI::isESIMD()); | ||
extractArgsAndReqsFromLambda(reinterpret_cast<char *>(KernelPtr), | ||
dongkyunahn-intel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
KI::getNumParams(), &KI::getParamDesc(0), | ||
KI::isESIMD()); | ||
MKernelName = KI::getName(); | ||
MOSModuleHandle = detail::OSUtil::getOSModuleHandle(KI::getName()); | ||
} else { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//==-------- atomic_intrin.hpp - Atomic intrinsic definition file ----------==// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
#pragma once | ||
|
||
#include <CL/sycl/exception.hpp> | ||
|
||
// This function implements atomic update of pre-existing variable in the | ||
// absense of C++ 20's atomic_ref. | ||
template <typename Ty> Ty atomic_add_fetch(Ty *ptr, Ty val) { | ||
dongkyunahn-intel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#ifdef _WIN32 | ||
// TODO: Windows will be supported soon | ||
throw cl::sycl::feature_not_supported(); | ||
#else | ||
return __atomic_add_fetch(ptr, val, __ATOMIC_RELAXED); | ||
#endif | ||
} |
Uh oh!
There was an error while loading. Please reload this page.