oneDPL
oneDPL copied to clipboard
Lazy `sycl::queue` creation in oneDPL hetero policies
Attention: ABI breaking change.
Yet another approach to lazy sycl::queue
creation in oneDPL hetero policies:
- the source issue described at https://github.com/oneapi-src/oneDPL/issues/1060
- the previous approach has been implemented by @adamfidel in the PR https://github.com/oneapi-src/oneDPL/pull/1154
The main implementation detail is std::once_flag
and ::std::call_once
usage packed into separate container
template <class TSYCLQueueFactory>
class sycl_queue_container
{
public:
template <typename... Args>
sycl::queue
get_queue(Args&&... args)
{
::std::call_once(__is_created, [&]() {
TSYCLQueueFactory factory;
__queue.emplace(factory(::std::forward<Args>(args)...));
});
assert(__queue.has_value());
return __queue.value();
}
private:
::std::once_flag __is_created;
::std::optional<sycl::queue> __queue;
};
This container shares between hetero policies instances:
template <typename TFactory>
using sycl_queue_container_ptr = ::std::shared_ptr<sycl_queue_container<TFactory>>;
// ...
template <typename KernelName = DefaultKernelName, class TSyclQueueFactory = TDefaultSYCLQueueFactory>
class device_policy
{
public:
// ...
private:
mutable sycl_queue_container_ptr<TSyclQueueFactory> q_container; // <<<<<<-- shared sycl::queue container
};
From my point of view this approach is correct because it's simple repeat something like sycl::queue
implementation (pimpl-implementation) and we don't introduce any new synchronization errors here.