Skip to content

Commit 13fe9fb

Browse files
authored
[SYCL] Add parallel_for interface simplification features (#1783)
This change implements "parallel_for simplification extension": https://github.com/intel/llvm/tree/sycl/sycl/doc/extensions/ParallelForSimpification Features list: - Allow parallel_for call with number or braced-init-list as the first argument, i.e. - Allow C++14 Generic lambda expression as the kernel for parallel_for, i.e [](auto){} - Allow C++14 Generic lambda expression as the kernel for parallel_for_work_group - Allow integral type as the kernel argument for parallel_for called with range<1>, e.g. [](int i){} - Allow item<1> to size_t conversion Changes: - Add overloads for parallel_for with range<1>, range<2> and range<3> to allow implicit conversion either from number or from braced-init-list. Extract the previously existing body to _impl function. - For generic lambda: Redesign the mechanism calculating lambda argument type. If the address of the Callable object can be taken, mechanism deduces the argument type, otherwise, uses the suggested type passed from the caller side. Calculate the lambda argument type once and use it further on when passing to kernel_parallel_for* function. Then the implementation of kernel_parallel_for* uses the calculated lambda argument type to determine the right overload of Builder::getElement by creating the pseudo object of lambda argument type. That allows easier integration of generic lambda support and allows to remove several overloads and instances. - For lambda with integral argument: if calculated lambda argument type is integral change it to item, otherwise, leave it as is. - Add conversion operator when item dimension is 1. accessor::operator[](size_t) is removed though to make it possible to pass the item to the mentioned operator. In that case we have accessor::operator[](id<>) left. Both number and item can be used with that operator because both of them are convertible to id. Otherwise, operator[] is ambiguous because item<1> is convertible to id and is convertible to size_t. Signed-off-by: Ruslan Arutyunyan <[email protected]>
1 parent 4a8c432 commit 13fe9fb

File tree

9 files changed

+325
-146
lines changed

9 files changed

+325
-146
lines changed

sycl/include/CL/sycl/accessor.hpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,6 @@ class accessor :
966966
return getQualifiedPtr()[LinearIndex];
967967
}
968968

969-
template <int Dims = Dimensions,
970-
typename = detail::enable_if_t<Dims == 1 && IsAccessAnyWrite>>
971-
RefType operator[](size_t Index) const {
972-
const size_t LinearIndex = getLinearIndex(id<Dimensions>(Index));
973-
return getQualifiedPtr()[LinearIndex];
974-
}
975-
976969
template <int Dims = Dimensions,
977970
typename = detail::enable_if_t<Dims == 0 && IsAccessReadOnly>>
978971
operator DataT() const {
@@ -987,13 +980,6 @@ class accessor :
987980
return getQualifiedPtr()[LinearIndex];
988981
}
989982

990-
template <int Dims = Dimensions,
991-
typename = detail::enable_if_t<Dims == 1 && IsAccessReadOnly>>
992-
DataT operator[](size_t Index) const {
993-
const size_t LinearIndex = getLinearIndex(id<Dimensions>(Index));
994-
return getQualifiedPtr()[LinearIndex];
995-
}
996-
997983
template <int Dims = Dimensions>
998984
operator typename detail::enable_if_t<
999985
Dims == 0 && AccessMode == access::mode::atomic, atomic<DataT, AS>>()

sycl/include/CL/sycl/detail/helpers.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,12 @@ class Builder {
139139
template <int N>
140140
using is_valid_dimensions = std::integral_constant<bool, (N > 0) && (N < 4)>;
141141

142-
template <int Dims> static const id<Dims> getId() {
142+
template <int Dims> static const id<Dims> getElement(id<Dims> *) {
143143
static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
144144
return __spirv::initGlobalInvocationId<Dims, id<Dims>>();
145145
}
146146

147-
template <int Dims> static const group<Dims> getGroup() {
147+
template <int Dims> static const group<Dims> getElement(group<Dims> *) {
148148
static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
149149
range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
150150
range<Dims> LocalSize{__spirv::initWorkgroupSize<Dims, range<Dims>>()};
@@ -172,7 +172,7 @@ class Builder {
172172
return createItem<Dims, false>(GlobalSize, GlobalId);
173173
}
174174

175-
template <int Dims> static const nd_item<Dims> getNDItem() {
175+
template <int Dims> static const nd_item<Dims> getElement(nd_item<Dims> *) {
176176
static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
177177
range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
178178
range<Dims> LocalSize{__spirv::initWorkgroupSize<Dims, range<Dims>>()};
@@ -188,6 +188,19 @@ class Builder {
188188
item<Dims, false> LocalItem = createItem<Dims, false>(LocalSize, LocalId);
189189
return createNDItem<Dims>(GlobalItem, LocalItem, Group);
190190
}
191+
192+
template <int Dims, bool WithOffset>
193+
static auto getElement(item<Dims, WithOffset> *)
194+
-> decltype(getItem<Dims, WithOffset>()) {
195+
return getItem<Dims, WithOffset>();
196+
}
197+
198+
template <int Dims>
199+
static auto getNDItem()
200+
-> decltype(getElement(static_cast<nd_item<Dims> *>(nullptr))) {
201+
return getElement(static_cast<nd_item<Dims> *>(nullptr));
202+
}
203+
191204
#endif // __SYCL_DEVICE_ONLY__
192205
};
193206

0 commit comments

Comments
 (0)