Skip to content

Commit 321965a

Browse files
committed
[SYCL] Use 0-dim accessors for scalar reductions
For buffers, reduction variables inherit dimensionality from accessors. For USM, reduction variables are assumed scalar without use of span. Signed-off-by: John Pennycook <[email protected]>
1 parent 22e9e2b commit 321965a

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

sycl/doc/extensions/reduction/reduction.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ unspecified reduction(accessor<T>& var, const T& identity, BinaryOperation combi
2626
2727
The exact behavior of a reduction is specific to an implementation; the only interface exposed to the user is the pair of functions above, which construct an unspecified `reduction` object encapsulating the reduction variable, an optional operator identity and the reduction operator. For user-defined binary operations, an implementation should issue a compile-time warning if an identity is not specified and this is known to negatively impact performance (e.g. as a result of the implementation choosing a different reduction algorithm). For standard binary operations (e.g. `std::plus`) on arithmetic types, the implementation must determine the correct identity automatically in order to avoid performance penalties.
2828
29-
Since SYCL 1.2.1 lacks a way to pass a single variable from the host into the `reduction` function, the reduction variable is specified using an accessor. If the accessor represents a buffer containing more than a single value of type `T`, reduction semantics are provided for the first value in the buffer. The access mode of the accessor determines whether the reduction variable's original value is included in the reduction (i.e. for `access::mode::read_write` it is included, and for `access::mode::discard_write` it is not). Multiple reductions aliasing the same output results in undefined behavior.
29+
The dimensionality of the `accessor` passed to the `reduction` function specifies the dimensionality of the reduction variable: a 0-dimensional `accessor` represents a scalar reduction, and any other dimensionality represents an array reduction. Specifying an array reduction of size N is functionally equivalent to specifying N independent scalar reductions. The access mode of the accessor determines whether the reduction variable's original value is included in the reduction (i.e. for `access::mode::read_write` it is included, and for `access::mode::discard_write` it is not). Multiple reductions aliasing the same output results in undefined behavior.
3030
3131
`T` must be trivially copyable, permitting an implementation to (optionally) use atomic operations to implement the reduction. This restriction is aligned with `std::atomic<T>` and `std::atomic_ref<T>`.
3232
@@ -75,7 +75,7 @@ queue.submit([&](handler& cgh)
7575
{
7676
auto a = a_buf.get_access<access::mode::read>(cgh);
7777
auto b = b_buf.get_access<access::mode::read>(cgh);
78-
auto sum = sum_buf.get_access<access::mode::write>(cgh);
78+
auto sum = accessor<int,0,access::mode::write,access::target::global_buffer>(sum_buf, cgh);
7979
cgh.parallel_for<class dot_product>(nd_range<1>{N, M}, reduction(sum, 0, plus<int>()), [=](nd_item<1> it, auto& sum)
8080
{
8181
int i = it.get_global_id(0);
@@ -84,18 +84,17 @@ queue.submit([&](handler& cgh)
8484
});
8585
```
8686

87-
# Array Reductions
87+
# Reductions using USM Pointers
8888

89-
SYCL buffers do not distinguish between scalars and arrays in the type system; a scalar in device memory must be represented as a buffer of size 1. This proposal assumes that the majority of reductions are scalar, and that a buffer passed to a reduction should therefore always be interpreted as a reduction of a single element. In order to support reductions of array types, we propose to treat them as a special-case: the user must explicitly request an array reduction by passing a `span` denoting the region of the buffer to include in the reduction. The semantics of an array reduction of size N should be equivalent to N independent reductions.
89+
Unlike a buffer, a [USM pointer](https://github.com/intel/llvm/tree/sycl/sycl/doc/extensions/usm) does not carry information describing the extent of the memory it points to; there is no way to distinguish between a scalar in device memory and an array. This proposal assumes that the majority of reductions are scalar, and that a pointer passed to a reduction should therefore always be interpreted as a reduction of a single element. The user must explicitly request an array reduction by passing a `span` denoting the memory region to include in the reduction.
9090

9191
## Example
9292

9393
```c++
94-
// Treat an input buffer as N independent reductions
94+
// Treat an input pointer as N independent reductions
95+
int* out = static_cast<int*>(sycl_malloc<alloc::shared>(4 * sizeof(int)));
9596
queue.submit([&](handler& cgh)
9697
{
97-
auto in = in_buf.get_access<access::mode::read>(cgh);
98-
auto out = out_buf.get_access<access::mode::write>(cgh);
9998
cgh.parallel_for<class sum>(nd_range<1>{N, M}, reduction(span(out, 4), 0, plus<int>()), [=](nd_item<1> it, auto& out)
10099
{
101100
int i = it.get_global_id(0);

0 commit comments

Comments
 (0)