Skip to content

Commit 6eb8b43

Browse files
authored
[SYCL] Support of iterator operations for zero-dimension accessors. (#9141)
* Zero dimension accessors allow access to only one element of the corresponding buffer. This PR handles iterator operators for zero dimension accessors by limiting the supported range to 1 element using `AccessorRange`. * Add support for 0-dim `local_accessor` iterator functionality. * Adds relevant tests.
1 parent 9035cdb commit 6eb8b43

File tree

2 files changed

+137
-20
lines changed

2 files changed

+137
-20
lines changed

sycl/include/sycl/accessor.hpp

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,9 @@ class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor :
12551255
std::conditional_t<AccessTarget == access::target::device,
12561256
global_ptr<value_type, IsDecorated>, value_type *>;
12571257

1258-
using iterator = typename detail::accessor_iterator<value_type, Dimensions>;
1258+
using iterator = typename detail::accessor_iterator<value_type, AdjustedDim>;
12591259
using const_iterator =
1260-
typename detail::accessor_iterator<const value_type, Dimensions>;
1260+
typename detail::accessor_iterator<const value_type, AdjustedDim>;
12611261
using reverse_iterator = std::reverse_iterator<iterator>;
12621262
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
12631263
using difference_type =
@@ -2035,18 +2035,16 @@ class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor :
20352035

20362036
bool empty() const noexcept { return size() == 0; }
20372037

2038-
template <int Dims = Dimensions, typename = std::enable_if_t<(Dims > 0)>>
2038+
template <int Dims = Dimensions,
2039+
typename = std::enable_if_t<Dims == Dimensions && (Dims > 0)>>
20392040
range<Dimensions> get_range() const {
2040-
return detail::convertToArrayOfN<Dimensions, 1>(getAccessRange());
2041+
return getRange<Dims>();
20412042
}
20422043

2043-
template <int Dims = Dimensions, typename = std::enable_if_t<(Dims > 0)>>
2044+
template <int Dims = Dimensions,
2045+
typename = std::enable_if_t<Dims == Dimensions && (Dims > 0)>>
20442046
id<Dimensions> get_offset() const {
2045-
static_assert(
2046-
!(PropertyListT::template has_property<
2047-
sycl::ext::oneapi::property::no_offset>()),
2048-
"Accessor has no_offset property, get_offset() can not be used");
2049-
return detail::convertToArrayOfN<Dimensions, 0>(getOffset());
2047+
return getOffset<Dims>();
20502048
}
20512049

20522050
template <int Dims = Dimensions, typename RefT = RefType,
@@ -2197,29 +2195,29 @@ class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor :
21972195
iterator begin() const noexcept {
21982196
return iterator::getBegin(
21992197
get_pointer(),
2200-
detail::convertToArrayOfN<Dimensions, 1>(getMemoryRange()), get_range(),
2201-
get_offset());
2198+
detail::convertToArrayOfN<AdjustedDim, 1>(getMemoryRange()),
2199+
getRange<AdjustedDim>(), getOffset<AdjustedDim>());
22022200
}
22032201

22042202
iterator end() const noexcept {
22052203
return iterator::getEnd(
22062204
get_pointer(),
2207-
detail::convertToArrayOfN<Dimensions, 1>(getMemoryRange()), get_range(),
2208-
get_offset());
2205+
detail::convertToArrayOfN<AdjustedDim, 1>(getMemoryRange()),
2206+
getRange<AdjustedDim>(), getOffset<AdjustedDim>());
22092207
}
22102208

22112209
const_iterator cbegin() const noexcept {
22122210
return const_iterator::getBegin(
22132211
get_pointer(),
2214-
detail::convertToArrayOfN<Dimensions, 1>(getMemoryRange()), get_range(),
2215-
get_offset());
2212+
detail::convertToArrayOfN<AdjustedDim, 1>(getMemoryRange()),
2213+
getRange<AdjustedDim>(), getOffset<AdjustedDim>());
22162214
}
22172215

22182216
const_iterator cend() const noexcept {
22192217
return const_iterator::getEnd(
22202218
get_pointer(),
2221-
detail::convertToArrayOfN<Dimensions, 1>(getMemoryRange()), get_range(),
2222-
get_offset());
2219+
detail::convertToArrayOfN<AdjustedDim, 1>(getMemoryRange()),
2220+
getRange<AdjustedDim>(), getOffset<AdjustedDim>());
22232221
}
22242222

22252223
reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
@@ -2233,6 +2231,23 @@ class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor :
22332231
}
22342232

22352233
private:
2234+
template <int Dims, typename = std::enable_if_t<(Dims > 0)>>
2235+
range<Dims> getRange() const {
2236+
if constexpr (Dimensions == 0)
2237+
return range<1>{1};
2238+
else
2239+
return detail::convertToArrayOfN<Dims, 1>(getAccessRange());
2240+
}
2241+
2242+
template <int Dims = Dimensions, typename = std::enable_if_t<(Dims > 0)>>
2243+
id<Dims> getOffset() const {
2244+
static_assert(
2245+
!(PropertyListT::template has_property<
2246+
sycl::ext::oneapi::property::no_offset>()),
2247+
"Accessor has no_offset property, get_offset() can not be used");
2248+
return detail::convertToArrayOfN<Dims, 0>(getOffset());
2249+
}
2250+
22362251
#ifdef __SYCL_DEVICE_ONLY__
22372252
size_t getTotalOffset() const noexcept {
22382253
size_t TotalOffset = 0;
@@ -2844,9 +2859,17 @@ class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor
28442859
bool empty() const noexcept { return this->size() == 0; }
28452860

28462861
iterator begin() const noexcept {
2847-
return &this->operator[](id<Dimensions>());
2862+
if constexpr (Dimensions == 0)
2863+
return local_acc::getQualifiedPtr();
2864+
else
2865+
return &this->operator[](id<Dimensions>());
2866+
}
2867+
iterator end() const noexcept {
2868+
if constexpr (Dimensions == 0)
2869+
return begin() + 1;
2870+
else
2871+
return begin() + this->size();
28482872
}
2849-
iterator end() const noexcept { return begin() + this->size(); }
28502873

28512874
const_iterator cbegin() const noexcept { return const_iterator(begin()); }
28522875
const_iterator cend() const noexcept { return const_iterator(end()); }

sycl/test-e2e/Basic/accessor/accessor.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,21 @@ int main() {
999999
}
10001000
assert(vec1[7] == 4 && vec2[15] == 4);
10011001
}
1002+
1003+
// 0-dim host_accessor iterator
1004+
{
1005+
std::vector<int> vec1(8);
1006+
{
1007+
sycl::buffer<int> buf1(vec1.data(), vec1.size());
1008+
sycl::host_accessor<int, 0> acc1(buf1);
1009+
*acc1.begin() = 4;
1010+
auto value = *acc1.cbegin();
1011+
value += *acc1.crbegin();
1012+
*acc1.rbegin() += value;
1013+
}
1014+
assert(vec1[0] == 12);
1015+
}
1016+
10021017
// Test swap() on basic accessor
10031018
{
10041019
std::vector<int> vec1(8), vec2(16);
@@ -1095,6 +1110,59 @@ int main() {
10951110
assert(Data == 64);
10961111
}
10971112

1113+
// iterator operations test for 0-dim buffer accessor
1114+
{
1115+
sycl::queue Queue;
1116+
int Data[] = {32, 32};
1117+
1118+
// Explicit block to prompt copy-back to Data
1119+
{
1120+
sycl::buffer<int, 1> DataBuffer(Data, sycl::range<1>(2));
1121+
1122+
Queue.submit([&](sycl::handler &CGH) {
1123+
sycl::accessor<int, 0> Acc(DataBuffer, CGH);
1124+
CGH.single_task<class acc_0_dim_iter_assignment>([=]() {
1125+
*Acc.begin() = 64;
1126+
auto value = *Acc.cbegin();
1127+
value += *Acc.crbegin();
1128+
*Acc.rbegin() += value;
1129+
});
1130+
});
1131+
Queue.wait();
1132+
}
1133+
1134+
assert(Data[0] == 64 * 3);
1135+
assert(Data[1] == 32);
1136+
}
1137+
1138+
// iterator operations test for 0-dim buffer accessor with target::host_task
1139+
{
1140+
sycl::queue Queue;
1141+
int Data[] = {32, 32};
1142+
1143+
using HostTaskAcc = sycl::accessor<int, 0, sycl::access::mode::read_write,
1144+
sycl::access::target::host_task>;
1145+
1146+
// Explicit block to prompt copy-back to Data
1147+
{
1148+
sycl::buffer<int, 1> DataBuffer(Data, sycl::range<1>(2));
1149+
1150+
Queue.submit([&](sycl::handler &CGH) {
1151+
HostTaskAcc Acc(DataBuffer, CGH);
1152+
CGH.host_task([=]() {
1153+
*Acc.begin() = 64;
1154+
auto value = *Acc.cbegin();
1155+
value += *Acc.crbegin();
1156+
*Acc.rbegin() += value;
1157+
});
1158+
});
1159+
Queue.wait();
1160+
}
1161+
1162+
assert(Data[0] == 64 * 3);
1163+
assert(Data[1] == 32);
1164+
}
1165+
10981166
// Assignment operator test for 0-dim local accessor
10991167
{
11001168
sycl::queue Queue;
@@ -1171,6 +1239,32 @@ int main() {
11711239
}
11721240
}
11731241

1242+
// Assignment operator test for 0-dim local accessor iterator
1243+
{
1244+
sycl::queue Queue;
1245+
int Data = 0;
1246+
1247+
// Explicit block to prompt copy-back to Data
1248+
{
1249+
sycl::buffer<int, 1> DataBuffer(&Data, sycl::range<1>(1));
1250+
1251+
Queue.submit([&](sycl::handler &CGH) {
1252+
sycl::accessor<int, 0> Acc(DataBuffer, CGH);
1253+
sycl::local_accessor<int, 0> LocalAcc(CGH);
1254+
CGH.parallel_for<class local_acc_0_dim_iter_assignment>(
1255+
sycl::nd_range<1>{1, 1}, [=](sycl::nd_item<1> ID) {
1256+
*LocalAcc.begin() = 32;
1257+
auto value = *LocalAcc.cbegin();
1258+
value += *LocalAcc.crbegin();
1259+
*LocalAcc.rbegin() += value;
1260+
Acc = LocalAcc;
1261+
});
1262+
});
1263+
}
1264+
1265+
assert(Data == 96);
1266+
}
1267+
11741268
// host_accessor hash
11751269
{
11761270
sycl::buffer<int> buffer1{sycl::range<1>{1}};

0 commit comments

Comments
 (0)