99#include < cstdint>
1010#include < functional>
1111#include < limits>
12+ #include < stdexcept>
13+ #include < string>
1214#include < thread>
15+ #include < utility>
1316#include < vector>
1417
18+ #ifdef ITLABAI_HAS_SYCL
19+ # include < sycl/sycl.hpp>
20+ #endif
21+
1522namespace it_lab_ai {
1623namespace parallel {
1724
@@ -20,7 +27,8 @@ enum class Backend : std::uint8_t {
2027 kThreads = 1 ,
2128 kTbb = 2 ,
2229 kOmp = 3 ,
23- kKokkos = 4
30+ kKokkos = 4 ,
31+ kSycl = 5
2432};
2533
2634struct Options {
@@ -149,5 +157,100 @@ inline void impl_kokkos(std::size_t count,
149157 Kokkos::fence ();
150158}
151159
160+ #ifdef ITLABAI_HAS_SYCL
161+ inline sycl::queue& sycl_queue () {
162+ static sycl::queue queue{sycl::default_selector_v};
163+ return queue;
164+ }
165+
166+ inline std::string sycl_device_name () {
167+ return sycl_queue ().get_device ().get_info <sycl::info::device::name>();
168+ }
169+
170+ template <typename T>
171+ class SyclSharedBuffer {
172+ public:
173+ explicit SyclSharedBuffer (std::size_t count)
174+ : count_(count), data_(count == 0 ? nullptr : sycl::malloc_shared<T>(
175+ count, sycl_queue())) {}
176+
177+ SyclSharedBuffer (const SyclSharedBuffer&) = delete ;
178+ SyclSharedBuffer& operator =(const SyclSharedBuffer&) = delete ;
179+
180+ SyclSharedBuffer (SyclSharedBuffer&& other) noexcept
181+ : count_(other.count_), data_(other.data_) {
182+ other.count_ = 0 ;
183+ other.data_ = nullptr ;
184+ }
185+
186+ SyclSharedBuffer& operator =(SyclSharedBuffer&& other) noexcept {
187+ if (this != &other) {
188+ release ();
189+ count_ = other.count_ ;
190+ data_ = other.data_ ;
191+ other.count_ = 0 ;
192+ other.data_ = nullptr ;
193+ }
194+ return *this ;
195+ }
196+
197+ ~SyclSharedBuffer () { release (); }
198+
199+ T* data () { return data_; }
200+ const T* data () const { return data_; }
201+ std::size_t size () const { return count_; }
202+
203+ void copy_from (const T* source) {
204+ for (std::size_t i = 0 ; i < count_; ++i) {
205+ data_[i] = source[i];
206+ }
207+ }
208+
209+ void copy_to (T* destination) const {
210+ for (std::size_t i = 0 ; i < count_; ++i) {
211+ destination[i] = data_[i];
212+ }
213+ }
214+
215+ private:
216+ void release () {
217+ if (data_ != nullptr ) {
218+ sycl::free (data_, sycl_queue ());
219+ data_ = nullptr ;
220+ count_ = 0 ;
221+ }
222+ }
223+
224+ std::size_t count_;
225+ T* data_;
226+ };
227+
228+ template <typename T>
229+ inline SyclSharedBuffer<T> make_sycl_shared_buffer (std::size_t count) {
230+ return SyclSharedBuffer<T>(count);
231+ }
232+
233+ template <typename Func>
234+ inline void impl_sycl (std::size_t count, Func&& func, const Options&) {
235+ if (count == 0 ) {
236+ return ;
237+ }
238+
239+ auto & queue = sycl_queue ();
240+ queue.parallel_for (sycl::range<1 >(count),
241+ [func = std::forward<Func>(func)](sycl::id<1 > index) {
242+ func (static_cast <std::size_t >(index[0 ]));
243+ });
244+ queue.wait_and_throw ();
245+ }
246+ #else
247+ template <typename Func>
248+ [[noreturn]] inline void impl_sycl (std::size_t , Func&&, const Options&) {
249+ throw std::runtime_error (
250+ " SYCL parallel backend was requested, but this target was not built with "
251+ " ITLABAI_HAS_SYCL" );
252+ }
253+ #endif
254+
152255} // namespace parallel
153256} // namespace it_lab_ai
0 commit comments