Buffer Wrappers

Buffer Wrappers#

// Defined in <oneapi/dpl/iterator>

namespace oneapi {
  namespace dpl {

    template < typename T, typename AllocatorT, typename TagT >
    /*unspecified*/ begin( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                           TagT tag = sycl::read_write );

    template < typename T, typename AllocatorT, typename TagT >
    /*unspecified*/ begin( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                           TagT tag, sycl::property::no_init );

    template < typename T, typename AllocatorT >
    /*unspecified*/ begin( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                           sycl::property::no_init );


    template < typename T, typename AllocatorT, typename TagT >
    /*unspecified*/ end( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                         TagT tag = sycl::read_write );

    template < typename T, typename AllocatorT, typename TagT >
    /*unspecified*/ end( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                         TagT tag, sycl::property::no_init );

    template < typename T, typename AllocatorT >
    /*unspecified*/ end( sycl::buffer<T, /*dim=*/1, AllocatorT> buf,
                         sycl::property::no_init );

  }
}

oneapi::dpl::begin and oneapi::dpl::end are helper functions for passing SYCL buffers to oneDPL algorithms. These functions accept a SYCL buffer and return a buffer position object, which type satisfies the following requirements but is otherwise unspecified:

  • It is copy-constructible and copy-assignable.

  • It is comparable with operator== and operator!=.

  • It provides the get_buffer() method that for a buffer position object returns the SYCL buffer, which the object was built over.

  • The expressions a + n and a - n, where a is a buffer position object and n is an integer value, are valid and evaluate to a buffer position object such that the corresponding position in the buffer follows (precedes) that of a by n. If this new position is out of the buffer bounds, the behavior is undefined.

  • The expression a - b, where a and b are buffer position objects, is valid and evaluates to an integer value n such that a == b + n.

If these operators and expressions are applied to buffer position objects that are not built over the same SYCL buffer, the behavior is undefined.

When invoking an algorithm, the buffer passed to begin should be the same as the buffer passed to end. Otherwise, the behavior is undefined.

An algorithm may return a buffer position object, which can then be compared and used in expressions with other objects built over the same buffer.

namespace dpl = oneapi::dpl; // see "Namespaces"
sycl::buffer buf {/*...*/};
auto pos = dpl::find(dpl::execution::dpcpp_default, dpl::begin(buf), dpl::end(buf), value);
int value_index = (pos == dpl::end(buf)) ? -1 : (pos - dpl::begin(buf));

Note

Though buffer position objects substitute for iterators as arguments and return values of oneDPL algorithms, they cannot be used as iterators in other contexts, including dereference, as their type does not satisfy the C++ standard requirements for an iterator.

SYCL deduction tags (the TagT parameters) and sycl::property::no_init allow to specify an access mode to be used by algorithms for accessing a SYCL buffer. The mode serves as a hint, and can be overridden depending on semantics of the algorithm. When invoking an algorithm, the same access mode arguments should be used for begin and end. Otherwise, the behavior is undefined.

namespace dpl = oneapi::dpl;
sycl::buffer buf {/*...*/};
auto policy = dpl::execution::dpcpp_default;

auto buf_begin = dpl::begin(buf, sycl::write_only);
auto buf_end_1 = dpl::end(buf, sycl::write_only); // arguments match begin()
dpl::fill(policy, buf_begin, buf_end_1, 42);      // OK
auto buf_end_2 = dpl::end(buf, sycl::write_only, sycl::no_init); // arguments do not match
dpl::fill(policy, buf_begin, buf_end_2, 42);                     // undefined behavior