blob: 936ea5991fd05a25c96772be2c8e2be5a1ddf86b [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declaration of the SYCL queue class, which
/// schedules kernels on a device.
///
//===----------------------------------------------------------------------===//
#ifndef _LIBSYCL___IMPL_QUEUE_HPP
#define _LIBSYCL___IMPL_QUEUE_HPP
#include <sycl/__impl/async_handler.hpp>
#include <sycl/__impl/context.hpp>
#include <sycl/__impl/device.hpp>
#include <sycl/__impl/event.hpp>
#include <sycl/__impl/handler.hpp>
#include <sycl/__impl/platform.hpp>
#include <sycl/__impl/property_list.hpp>
#include <sycl/__impl/detail/config.hpp>
#include <sycl/__impl/detail/get_device_kernel_info.hpp>
#include <sycl/__impl/detail/kernel_arg_helpers.hpp>
#include <sycl/__impl/detail/kernel_submission.hpp>
#include <sycl/__impl/detail/obj_utils.hpp>
#include <sycl/__impl/detail/unified_range_view.hpp>
#include <sycl/__impl/exception.hpp>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
class context;
namespace detail {
class MockQueue;
class QueueImpl;
template <typename, typename T> struct CheckFunctionCallOperator {
static_assert(std::integral_constant<T, false>::value,
"Second template parameter is required to be of function type");
};
template <typename F, typename RetT, typename... Args>
struct CheckFunctionCallOperator<F, RetT(Args...)> {
private:
template <typename T>
static constexpr auto check(T *) ->
typename std::is_same<decltype(std::declval<std::add_const_t<T>>()
.operator()(std::declval<Args>()...)),
RetT>::type;
template <typename> static constexpr std::false_type check(...);
using type = decltype(check<F>(0));
public:
static constexpr bool value = type::value;
};
} // namespace detail
class TypelessCGF {
public:
template <class T>
TypelessCGF(T &&F)
// NOTE: Even if `F` is a pointer to a function, `&F` is a pointer to a
// pointer to a function and as such can be cast to `void *` (pointer to
// a function cannot be cast).
: Object(static_cast<const void *>(&F)),
InvokerF(&Invoker<std::remove_reference_t<T>>::call) {}
~TypelessCGF() = default;
TypelessCGF(const TypelessCGF &) = delete;
TypelessCGF(TypelessCGF &&) = delete;
TypelessCGF &operator=(const TypelessCGF &) = delete;
TypelessCGF &operator=(TypelessCGF &&) = delete;
void operator()(handler &CGH) const { InvokerF(Object, CGH); }
private:
// SYCL 2020 command group function object is a type that is callable with
// operator(), takes a reference to a command group handler, and defines
// a command group that can be submitted by a queue. The function object can
// be a named type, lambda expression or std::function.
template <typename T> struct Invoker {
static void call(const void *Object, handler &CGH) {
(*const_cast<T *>(static_cast<const T *>(Object)))(CGH);
}
};
const void *Object;
using InvokerTy = void (*)(const void *, handler &);
const InvokerTy InvokerF;
};
// SYCL 2020 4.6.5. Queue class.
class _LIBSYCL_EXPORT queue : private detail::KernelSubmissionBase<queue> {
public:
queue(const queue &rhs) = default;
queue(queue &&rhs) = default;
queue &operator=(const queue &rhs) = default;
queue &operator=(queue &&rhs) = default;
~queue() = default;
friend bool operator==(const queue &lhs, const queue &rhs) {
return lhs.impl == rhs.impl;
}
friend bool operator!=(const queue &lhs, const queue &rhs) {
return !(lhs == rhs);
}
/// Constructs a SYCL queue instance using the device returned by an instance
/// of default_selector.
///
/// \param propList is a list of properties for queue construction.
explicit queue(const property_list &propList = {})
: queue(detail::SelectDevice(default_selector_v), async_handler{},
propList) {}
/// Constructs a SYCL queue instance with an async_handler using the device
/// returned by an instance of default_selector.
///
/// \param asyncHandler is a SYCL asynchronous exception handler.
/// \param propList is a list of properties for queue construction.
explicit queue(const async_handler &asyncHandler,
const property_list &propList = {})
: queue(detail::SelectDevice(default_selector_v), asyncHandler,
propList) {}
/// Constructs a SYCL queue instance using the device identified by the
/// device selector provided.
/// \param deviceSelector is a SYCL 2020 Device Selector, a simple callable
/// that takes a device and returns an int
/// \param propList is a list of properties for queue construction.
template <
typename DeviceSelector,
typename = detail::EnableIfDeviceSelectorIsInvocable<DeviceSelector>>
explicit queue(const DeviceSelector &deviceSelector,
const property_list &propList = {})
: queue(detail::SelectDevice(deviceSelector), async_handler{}, propList) {
}
/// Constructs a SYCL queue instance using the device identified by the
/// device selector provided.
/// \param deviceSelector is a SYCL 2020 Device Selector, a simple callable
/// that takes a device and returns an int
/// \param asyncHandler is a SYCL asynchronous exception handler.
/// \param propList is a list of properties for queue construction.
template <
typename DeviceSelector,
typename = detail::EnableIfDeviceSelectorIsInvocable<DeviceSelector>>
explicit queue(const DeviceSelector &deviceSelector,
const async_handler &asyncHandler,
const property_list &propList = {})
: queue(detail::SelectDevice(deviceSelector), asyncHandler, propList) {}
/// Constructs a SYCL queue instance using the device provided.
///
/// \param syclDevice is an instance of SYCL device.
/// \param propList is a list of properties for queue construction.
explicit queue(const device &syclDevice, const property_list &propList = {})
: queue(syclDevice, async_handler{}, propList) {}
/// Constructs a SYCL queue instance with an async_handler using the device
/// provided.
///
/// \param syclDevice is an instance of SYCL device.
/// \param asyncHandler is a SYCL asynchronous exception handler.
/// \param propList is a list of properties for queue construction.
explicit queue(const device &syclDevice, const async_handler &asyncHandler,
const property_list &propList = {})
: queue(syclDevice.get_platform().khr_get_default_context(), syclDevice,
asyncHandler, propList) {}
/// Constructs a SYCL queue instance that is associated with syclContext,
/// using the device identified by the device selector provided.
///
/// \param syclContext is the context to associate the queue with.
/// \param deviceSelector is a SYCL 2020 Device Selector, a simple callable
/// that takes a device and returns an int
/// \param propList is a list of properties for queue construction.
/// \throw sycl::exception with sycl::errc::invalid if syclContext does not
/// contain the selected device.
template <
typename DeviceSelector,
typename = detail::EnableIfDeviceSelectorIsInvocable<DeviceSelector>>
explicit queue(const context &syclContext,
const DeviceSelector &deviceSelector,
const property_list &propList = {})
: queue(syclContext, detail::SelectDevice(deviceSelector), propList) {}
/// Constructs a SYCL queue instance with an async_handler that is associated
/// with syclContext, using the device identified by the device selector
/// provided.
///
/// \param syclContext is the context to associate the queue with.
/// \param deviceSelector is a SYCL 2020 Device Selector, a simple callable
/// that takes a device and returns an int
/// \param asyncHandler is a SYCL asynchronous exception handler.
/// \param propList is a list of properties for queue construction.
/// \throw sycl::exception with sycl::errc::invalid if syclContext does not
/// contain the selected device.
template <
typename DeviceSelector,
typename = detail::EnableIfDeviceSelectorIsInvocable<DeviceSelector>>
explicit queue(const context &syclContext,
const DeviceSelector &deviceSelector,
const async_handler &asyncHandler,
const property_list &propList = {})
: queue(syclContext, detail::SelectDevice(deviceSelector), asyncHandler,
propList) {}
/// Constructs a SYCL queue instance that is associated with syclContext,
/// using the device provided.
///
/// \param syclContext is the context to associate the queue with.
/// \param syclDevice is an instance of SYCL device.
/// \param propList is a list of properties for queue construction.
/// \throw sycl::exception with sycl::errc::invalid if syclContext does not
/// contain syclDevice.
explicit queue(const context &syclContext, const device &syclDevice,
const property_list &propList = {});
/// Constructs a SYCL queue instance with an async_handler that is associated
/// with syclContext, using the device provided.
///
/// \param syclContext is the context to associate the queue with.
/// \param syclDevice is an instance of SYCL device.
/// \param asyncHandler is a SYCL asynchronous exception handler.
/// \param propList is a list of properties for queue construction.
/// \throw sycl::exception with sycl::errc::invalid if syclContext does not
/// contain syclDevice.
explicit queue(const context &syclContext, const device &syclDevice,
const async_handler &asyncHandler,
const property_list &propList = {});
/// \return the SYCL backend associated with this queue.
backend get_backend() const noexcept;
/// \return the associated SYCL context.
context get_context() const;
/// \return the SYCL device this queue was constructed with.
device get_device() const;
/// Equivalent to has_property<property::queue::in_order>().
///
/// \return true if and only if the queue is in order.
bool is_in_order() const;
/// Queries the queue for information.
///
/// The return type depends on information being queried.
template <typename Param> typename Param::return_type get_info() const;
/// Queries the queue for SYCL backend-specific information.
///
/// The return type depends on the information being queried.
template <typename Param>
typename Param::return_type get_backend_info() const;
/// Blocks the calling thread until all commands previously submitted to this
/// queue have completed. Synchronous errors are reported through SYCL
/// exceptions.
void wait();
/// Blocks the calling thread until all commands previously submitted to this
/// queue have completed. Synchronous errors are reported through SYCL
/// exceptions. At least all unconsumed asynchronous errors held by this queue
/// are passed to the async_handler associated with the queue.
void wait_and_throw();
/// Checks to see if any unconsumed asynchronous errors have been produced by
/// the queue and if so reports them by passing them to the async_handler
/// associated with the queue.
void throw_asynchronous();
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type.
///
/// \param kernelFunc is the kernel functor or lambda.
/// \return an event that represents the status of the submitted kernel.
template <typename KernelName = detail::AutoName, typename KernelType>
event single_task(const KernelType &kernelFunc) {
return single_task<KernelName, KernelType>(std::vector<event>{},
kernelFunc);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type.
///
/// \param depEvent is an event that specifies the kernel dependency.
/// \param kernelFunc is the kernel functor or lambda.
/// \return an event that represents the status of the submitted kernel.
template <typename KernelName = detail::AutoName, typename KernelType>
event single_task(event depEvent, const KernelType &kernelFunc) {
return single_task<KernelName, KernelType>(std::vector<event>{depEvent},
kernelFunc);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type.
///
/// \param depEvents is a collection of events that specify the kernel
/// dependencies.
/// \param kernelFunc is the kernel functor or lambda.
/// \return an event that represents the status of the submitted kernel.
template <typename KernelName = detail::AutoName, typename KernelType>
event single_task(const std::vector<event> &depEvents,
const KernelType &kernelFunc) {
static_assert(
detail::CheckFunctionCallOperator<std::remove_reference_t<KernelType>,
void()>::value,
"Invalid kernel function signature.");
setKernelLaunchParams(depEvents);
using NameT =
typename detail::get_kernel_name_t<KernelName, KernelType>::name;
submitSingleTask<NameT, KernelType>(kernelFunc);
return getLastEvent();
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<1> numWorkItems, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems, std::vector<event>{},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<2> numWorkItems, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems, std::vector<event>{},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<3> numWorkItems, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems, std::vector<event>{},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param depEvent adds a requirement that the action represented by depEvent
/// must complete before executing this kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<1> numWorkItems, event depEvent, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems,
std::vector<event>{depEvent},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param depEvent adds a requirement that the action represented by depEvent
/// must complete before executing this kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<2> numWorkItems, event depEvent, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems,
std::vector<event>{depEvent},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel.
/// \param depEvent adds a requirement that the action represented by depEvent
/// must complete before executing this kernel.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<3> numWorkItems, event depEvent, Rest &&...rest) {
return parallel_for<KernelName, Rest...>(numWorkItems,
std::vector<event>{depEvent},
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel
/// \param depEvents is a vector of events that specifies the kernel
/// dependencies.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<1> numWorkItems, const std::vector<event> &depEvents,
Rest &&...rest) {
return parallelForImpl<KernelName>(numWorkItems, depEvents,
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel
/// \param depEvents is a vector of events that specifies the kernel
/// dependencies.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<2> numWorkItems, const std::vector<event> &depEvents,
Rest &&...rest) {
return parallelForImpl<KernelName>(numWorkItems, depEvents,
std::forward<Rest>(rest)...);
}
/// Defines and invokes a SYCL kernel function as a lambda expression or a
/// named function object type, for the specified range.
///
/// \param numWorkItems specifies the global work space of the kernel
/// \param depEvents is a vector of events that specifies the kernel
/// dependencies.
/// \param rest acts as if it was "const KernelType &KernelFunc".
// TODO: Rest will represent reduction types once it is supported.
template <typename KernelName = detail::AutoName, typename... Rest>
event parallel_for(range<3> numWorkItems, const std::vector<event> &depEvents,
Rest &&...rest) {
return parallelForImpl<KernelName>(numWorkItems, depEvents,
std::forward<Rest>(rest)...);
}
template <typename KernelName = detail::AutoName, int Dims, typename... Rest>
event parallel_for(nd_range<Dims> executionRange, Rest &&...rest) {
return parallel_for<KernelName, Dims, Rest...>(
executionRange, std::vector<event>{}, std::forward<Rest>(rest)...);
}
template <typename KernelName = detail::AutoName, int Dims, typename... Rest>
event parallel_for(nd_range<Dims> executionRange, event depEvent,
Rest &&...rest) {
return parallel_for<KernelName, Dims, Rest...>(executionRange,
std::vector<event>{depEvent},
std::forward<Rest>(rest)...);
}
template <typename KernelName = detail::AutoName, int Dims, typename... Rest>
event parallel_for(nd_range<Dims> executionRange,
const std::vector<event> &depEvents, Rest &&...rest) {
detail::checkNDRangeAndThrow(executionRange);
return parallelForImpl<KernelName>(executionRange, depEvents,
std::forward<Rest>(rest)...);
}
/// Submits a memory copy operation from one USM or host pointer to another.
/// USM pointers must be accessible on the device associated with the queue.
///
/// \param dest is the pointer to copy to.
/// \param src is the pointer to copy from.
/// \param numBytes is the number of bytes to copy.
/// \return an event that represents the status of the operation.
event memcpy(void *dest, const void *src, std::size_t numBytes) {
return memcpy(dest, src, numBytes, std::vector<event>{});
}
/// Submits a memory copy operation from one USM or host pointer to another.
/// USM pointers must be accessible on the device associated with the queue.
///
/// \param dest is the pointer to copy to.
/// \param src is the pointer to copy from.
/// \param numBytes is the number of bytes to copy.
/// \param depEvent is an event that represents a dependency for the
/// operation.
/// \return an event that represents the status of the operation.
event memcpy(void *dest, const void *src, std::size_t numBytes,
event depEvent) {
return memcpy(dest, src, numBytes, std::vector<event>{depEvent});
}
/// Submits a memory copy operation from one USM or host pointer to another.
/// USM pointers must be accessible on the device associated with the queue.
///
/// \param dest is the pointer to copy to.
/// \param src is the pointer to copy from.
/// \param numBytes is the number of bytes to copy.
/// \param depEvents is a vector of events that represent dependencies for the
/// operation.
/// \return an event that represents the status of the operation.
event memcpy(void *dest, const void *src, std::size_t numBytes,
const std::vector<event> &depEvents);
/// Submits a memset operation on a USM allocation that must be accessible
/// on the device associated with the queue. Equivalent to a fill operation
/// with an unsigned char pattern.
///
/// \param ptr is the pointer to memory to be set.
/// \param value is the value the memory should be filled with, interpreted
/// as an unsigned char.
/// \param numBytes is the number of bytes to set.
/// \return an event that represents the status of the operation.
event memset(void *ptr, int value, std::size_t numBytes) {
return memset(ptr, value, numBytes, std::vector<event>{});
}
/// Submits a memset operation on a USM allocation that must be accessible
/// on the device associated with the queue. Equivalent to a fill operation
/// with an unsigned char pattern.
///
/// \param ptr is the pointer to memory to be set.
/// \param value is the value the memory should be filled with, interpreted
/// as an unsigned char.
/// \param numBytes is the number of bytes to set.
/// \param depEvent is an event that represents a dependency for the
/// operation.
/// \return an event that represents the status of the operation.
event memset(void *ptr, int value, std::size_t numBytes, event depEvent) {
return memset(ptr, value, numBytes, std::vector<event>{depEvent});
}
/// Submits a memset operation on a USM allocation that must be accessible
/// on the device associated with the queue. Equivalent to a fill operation
/// with an unsigned char pattern.
///
/// \param ptr is the pointer to memory to be set.
/// \param value is the value the memory should be filled with, interpreted
/// as an unsigned char.
/// \param numBytes is the number of bytes to set.
/// \param depEvents is a vector of events that represent dependencies for the
/// operation.
/// \return an event that represents the status of the operation.
event memset(void *ptr, int value, std::size_t numBytes,
const std::vector<event> &depEvents) {
return fill(ptr, static_cast<unsigned char>(value), numBytes, depEvents);
}
/// Submits a fill operation that replicates a pattern into a USM allocation
/// that must be accessible on the device associated with the queue.
///
/// \param ptr is the pointer to memory to be filled.
/// \param pattern is the pattern to be replicated.
/// \param count is the number of times the pattern is replicated.
/// \return an event that represents the status of the operation.
template <typename T>
event fill(void *ptr, const T &pattern, std::size_t count) {
return fill(ptr, pattern, count, std::vector<event>{});
}
/// Submits a fill operation that replicates a pattern into a USM allocation
/// that must be accessible on the device associated with the queue.
///
/// \param ptr is the pointer to memory to be filled.
/// \param pattern is the pattern to be replicated.
/// \param count is the number of times the pattern is replicated.
/// \param depEvent is an event that represents a dependency for the
/// operation.
/// \return an event that represents the status of the operation.
template <typename T>
event fill(void *ptr, const T &pattern, std::size_t count, event depEvent) {
return fill(ptr, pattern, count, std::vector<event>{depEvent});
}
/// Submits a fill operation that replicates a pattern into a USM allocation
/// that must be accessible on the device associated with the queue.
///
/// \param ptr is the pointer to memory to be filled.
/// \param pattern is the pattern to be replicated.
/// \param count is the number of times the pattern is replicated.
/// \param depEvents is a vector of events that represent dependencies for the
/// operation.
/// \return an event that represents the status of the operation.
template <typename T>
event fill(void *ptr, const T &pattern, std::size_t count,
const std::vector<event> &depEvents) {
return fillImpl(ptr, &pattern, sizeof(T), count, depEvents);
}
/// Immediately calls the command group function object.
///
/// The command group may submit no more than one command to this queue for
/// execution on the associated device.
///
/// \param cgf command group function object.
/// \return an event that represents the status of the submitted command.
template <typename T>
std::enable_if_t<std::is_invocable_r_v<void, T, handler &>, event>
submit(T cgf) {
return submitWithHandler(cgf);
}
/// Immediately calls the command group function object.
///
/// The command group may submit no more than one command to this queue for
/// execution on the associated device. On a kernel error, this command group
/// may be scheduled for execution on \p secondaryQueue.
///
/// \param cgf command group function object.
/// \param secondaryQueue queue used as a fallback for kernel errors. Unused
/// (See SYCL 2020 3.9.10. Fallback mechanism).
/// \return an event that represents the status of the submitted command.
template <typename T>
std::enable_if_t<std::is_invocable_r_v<void, T, handler &>, event>
submit(T cgf, [[maybe_unused]] queue &secondaryQueue) {
return submitWithHandler(cgf);
}
/// Provides hints to the runtime library that data can be made available
/// on a device earlier than Unified Shared Memory would normally require it
/// to be available.
///
/// \param ptr is a USM pointer to the memory to be prefetched to the device.
/// \param numBytes is a number of bytes to be prefetched.
/// \return an event representing prefetch operation.
event prefetch(void *ptr, std::size_t numBytes) {
return prefetch(ptr, numBytes, std::vector<event>{});
}
/// Provides hints to the runtime library that data can be made available
/// on a device earlier than Unified Shared Memory would normally require it
/// to be available.
///
/// \param ptr is a USM pointer to the memory to be prefetched to the device.
/// \param numBytes is a number of bytes to be prefetched.
/// \param depEvent is an event that specifies the kernel dependencies.
/// \return an event representing prefetch operation.
event prefetch(void *ptr, std::size_t numBytes, event depEvent) {
return prefetch(ptr, numBytes, std::vector<event>{depEvent});
}
/// Provides hints to the runtime library that data can be made available
/// on a device earlier than Unified Shared Memory would normally require it
/// to be available.
///
/// \param ptr is a USM pointer to the memory to be prefetched to the device.
/// \param numBytes is a number of bytes to be prefetched.
/// \param depEvents is a vector of events that specify the kernel
/// dependencies.
/// \return an event representing prefetch operation.
event prefetch(void *ptr, std::size_t numBytes,
const std::vector<event> &depEvents);
private:
template <typename KernelName, int Dims, template <int> class Range,
typename... Rest>
event parallelForImpl(Range<Dims> numWorkItems,
const std::vector<event> &depEvents, Rest &&...rest) {
setKernelLaunchParams(depEvents, numWorkItems);
detail::KernelSubmissionBase<queue>::template parallelForImpl<KernelName>(
numWorkItems, std::forward<Rest>(rest)...);
return getLastEvent();
}
/// Passes kernel dependencies and execution range to the runtime.
/// \param Events a collection of events representing dependencies of the
/// kernel to submit.
/// \param Range a unified view of the kernel execution range.
void setKernelLaunchParams(const std::vector<event> &Events,
const detail::UnifiedRangeView &Range = {});
/// Passes kernel arguments to runtime.
/// \param KernelInfo the information for the kernel being invoked.
/// \param ArgData a pointer to the kernel argument.
/// \param ArgSize the size of the kernel argument.
void submitKernelImpl(detail::DeviceKernelInfo &KernelInfo, void *ArgData,
size_t ArgSize);
/// \return an event representing last kernel invocation.
event getLastEvent();
/// Submits a fill operation that replicates a pattern into a USM allocation
/// that must be accessible on the device associated with the queue.
///
/// \param Ptr is the pointer to memory to be filled.
/// \param Pattern is the pattern to be replicated.
/// \param PatternSize is the size of the pattern in bytes.
/// \param Count is the number of times the pattern is replicated.
/// \param DepEvents is a vector of events that represent dependencies for the
/// operation.
/// \return an event that represents the status of the operation.
event fillImpl(void *Ptr, const void *Pattern, std::size_t PatternSize,
std::size_t Count, const std::vector<event> &DepEvents);
event submitWithHandler(const TypelessCGF &CGF);
queue(const std::shared_ptr<detail::QueueImpl> &Impl) : impl(Impl) {}
std::shared_ptr<detail::QueueImpl> impl;
friend sycl::detail::ImplUtils;
friend sycl::detail::MockQueue;
friend class detail::KernelSubmissionBase<queue>;
}; // class queue
_LIBSYCL_END_NAMESPACE_SYCL
template <>
struct std::hash<sycl::queue> : public sycl::detail::HashBase<sycl::queue> {};
#endif // _LIBSYCL___IMPL_QUEUE_HPP