21#include <cuda_runtime.h>
25#include <tbb/parallel_for.h>
28#if defined(SYCL_LANGUAGE_VERSION)
37static constexpr int64_t OPEN3D_PARFOR_BLOCK = 128;
38static constexpr int64_t OPEN3D_PARFOR_THREAD = 4;
41template <
int64_t block_size,
int64_t thread_size,
typename func_t>
42__global__
void ElementWiseKernel_(int64_t n, func_t f) {
43 int64_t items_per_block = block_size * thread_size;
44 int64_t idx = blockIdx.x * items_per_block + threadIdx.x;
46 for (int64_t i = 0; i < thread_size; ++i) {
55template <
typename func_t>
56void ParallelForCUDA_(
const Device& device, int64_t n,
const func_t& func) {
58 utility::LogError(
"ParallelFor for CUDA cannot run on device {}.",
65 CUDAScopedDevice scoped_device(device);
66 int64_t items_per_block = OPEN3D_PARFOR_BLOCK * OPEN3D_PARFOR_THREAD;
67 int64_t grid_size = (n + items_per_block - 1) / items_per_block;
69 ElementWiseKernel_<OPEN3D_PARFOR_BLOCK, OPEN3D_PARFOR_THREAD>
70 <<<grid_size, OPEN3D_PARFOR_BLOCK, 0, core::cuda::GetStream()>>>(
82template <
typename func_t>
87 if (!device.
IsCPU()) {
88 utility::LogError(
"ParallelFor for CPU cannot run on device {}.",
95 tbb::parallel_for(tbb::blocked_range<int64_t>(0, n, grain_size),
96 [&func](
const tbb::blocked_range<int64_t>& range) {
97 for (int64_t i = range.begin(); i < range.end();
109template <
typename func_t>
118#if defined(SYCL_LANGUAGE_VERSION)
125template <
typename func_t>
126sycl::event ParallelForSYCLImpl_(sycl::queue&
queue,
129 const std::vector<sycl::event>& deps) {
131 return sycl::event();
133 size_t wg = core::sy::PreferredWorkGroupSize(
queue.get_device());
134 const size_t global_size = ((
static_cast<size_t>(n) + wg - 1) / wg) * wg;
135 sycl::nd_range<1> nd_range{sycl::range<1>(global_size), sycl::range<1>(wg)};
136 return queue.parallel_for(nd_range, deps, [=](sycl::nd_item<1> item) {
137 int64_t i = item.get_global_id(0);
145template <
typename func_t>
146void ParallelForSYCL_(
const Device& device, int64_t n,
const func_t& func) {
147 if (!device.IsSYCL()) {
148 utility::LogError(
"ParallelFor for SYCL cannot run on device {}.",
152 ParallelForSYCLImpl_(
queue, n, func, {}).wait_and_throw();
160template <
typename func_t>
161sycl::event ParallelForSYCL_(
const Device& device,
164 const std::vector<sycl::event>& deps) {
165 if (!device.IsSYCL()) {
166 utility::LogError(
"ParallelFor for SYCL cannot run on device {}.",
170 return ParallelForSYCLImpl_(
queue, n, func, deps);
189template <
typename func_t>
192 ParallelForCUDA_(device, n, func);
193#elif defined(SYCL_LANGUAGE_VERSION)
195 ParallelForSYCL_(device, n, func);
204#if defined(SYCL_LANGUAGE_VERSION)
219template <
typename func_t>
223 std::initializer_list<sycl::event> deps) {
224 return ParallelForSYCL_(device, n, func, std::vector<sycl::event>(deps));
236template <
typename func_t>
238 ParallelForSYCLImpl_(
queue, n, func, {}).wait_and_throw();
242template <
typename func_t>
246 const std::vector<sycl::event>& deps) {
247 return ParallelForSYCLImpl_(
queue, n, func, deps);
250template <
typename func_t>
254 std::initializer_list<sycl::event> deps) {
305template <
typename vec_func_t,
typename func_t>
309 const vec_func_t& vec_func) {
310#ifdef BUILD_ISPC_MODULE
313 ParallelForCUDA_(device, n, func);
314#elif defined(SYCL_LANGUAGE_VERSION)
316 ParallelForSYCL_(device, n, func);
323 int64_t start = n * i / num_threads;
324 int64_t end = std::min<int64_t>(n * (i + 1) / num_threads, n);
325 vec_func(start, end);
332 int64_t start = n * i / num_threads;
333 int64_t end = std::min<int64_t>(n * (i + 1) / num_threads, n);
334 vec_func(start, end);
341 ParallelForCUDA_(device, n, func);
342#elif defined(SYCL_LANGUAGE_VERSION)
344 ParallelForSYCL_(device, n, func);
355#ifdef BUILD_ISPC_MODULE
358#define OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, ...) \
359 using namespace ispc; \
360 ISPCKernel(start, end, __VA_ARGS__);
365#define OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, ...) \
367 "ISPC module disabled. Unable to call vectorized kernel {}", \
368 OPEN3D_STRINGIFY(ISPCKernel));
373#define OPEN3D_OVERLOADED_LAMBDA_(T, ISPCKernel, ...) \
374 [&](T, int64_t start, int64_t end) { \
375 OPEN3D_CALL_ISPC_KERNEL_( \
376 OPEN3D_CONCAT(ISPCKernel, OPEN3D_CONCAT(_, T)), start, end, \
389#define OPEN3D_VECTORIZED(ISPCKernel, ...) \
390 [&](int64_t start, int64_t end) { \
391 OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, __VA_ARGS__); \
407#define OPEN3D_TEMPLATE_VECTORIZED(T, ISPCKernel, ...) \
408 [&](int64_t start, int64_t end) { \
409 static_assert(std::is_arithmetic<T>::value, \
410 "Data type is not an arithmetic type"); \
412 OPEN3D_OVERLOADED_LAMBDA_(bool, ISPCKernel, __VA_ARGS__), \
413 OPEN3D_OVERLOADED_LAMBDA_(uint8_t, ISPCKernel, __VA_ARGS__), \
414 OPEN3D_OVERLOADED_LAMBDA_(int8_t, ISPCKernel, __VA_ARGS__), \
415 OPEN3D_OVERLOADED_LAMBDA_(uint16_t, ISPCKernel, __VA_ARGS__), \
416 OPEN3D_OVERLOADED_LAMBDA_(int16_t, ISPCKernel, __VA_ARGS__), \
417 OPEN3D_OVERLOADED_LAMBDA_(uint32_t, ISPCKernel, __VA_ARGS__), \
418 OPEN3D_OVERLOADED_LAMBDA_(int32_t, ISPCKernel, __VA_ARGS__), \
419 OPEN3D_OVERLOADED_LAMBDA_(uint64_t, ISPCKernel, __VA_ARGS__), \
420 OPEN3D_OVERLOADED_LAMBDA_(int64_t, ISPCKernel, __VA_ARGS__), \
421 OPEN3D_OVERLOADED_LAMBDA_(float, ISPCKernel, __VA_ARGS__), \
422 OPEN3D_OVERLOADED_LAMBDA_(double, ISPCKernel, __VA_ARGS__), \
423 [&](auto&& generic, int64_t start, int64_t end) { \
425 "Unsupported data type {} for calling " \
426 "vectorized kernel {}", \
427 typeid(generic).name(), \
428 OPEN3D_STRINGIFY(ISPCKernel)); \
429 })(T{}, start, end); \
#define OPEN3D_GET_LAST_CUDA_ERROR(message)
Definition CUDAUtils.h:47
sycl::queue queue
Definition SYCLContext.cpp:88
bool IsSYCL() const
Returns true iff device type is SYCL GPU.
Definition Device.h:54
bool IsCPU() const
Returns true iff device type is CPU.
Definition Device.h:48
std::string ToString() const
Returns string representation of device, e.g. "CPU:0", "CUDA:0".
Definition Device.cpp:94
sycl::queue GetQueue(const Device &device)
Definition SYCLContext.cpp:183
void ParallelForCPU_(const Device &device, int64_t n, int64_t grain_size, const func_t &func)
Definition ParallelFor.h:83
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition ParallelFor.h:190
std::size_t & DefaultGrainSizeTBB2D() noexcept
Definition Parallel.cpp:43
int EstimateMaxThreads()
Definition Parallel.cpp:22
Definition PinholeCameraIntrinsic.cpp:16