21#include <cuda_runtime.h>
26#if defined(SYCL_LANGUAGE_VERSION)
35static constexpr int64_t OPEN3D_PARFOR_BLOCK = 128;
36static constexpr int64_t OPEN3D_PARFOR_THREAD = 4;
39template <
int64_t block_size,
int64_t thread_size,
typename func_t>
40__global__
void ElementWiseKernel_(int64_t n, func_t f) {
41 int64_t items_per_block = block_size * thread_size;
42 int64_t idx = blockIdx.x * items_per_block + threadIdx.x;
44 for (int64_t i = 0; i < thread_size; ++i) {
53template <
typename func_t>
54void ParallelForCUDA_(
const Device& device, int64_t n,
const func_t& func) {
56 utility::LogError(
"ParallelFor for CUDA cannot run on device {}.",
63 CUDAScopedDevice scoped_device(device);
64 int64_t items_per_block = OPEN3D_PARFOR_BLOCK * OPEN3D_PARFOR_THREAD;
65 int64_t grid_size = (n + items_per_block - 1) / items_per_block;
67 ElementWiseKernel_<OPEN3D_PARFOR_BLOCK, OPEN3D_PARFOR_THREAD>
68 <<<grid_size, OPEN3D_PARFOR_BLOCK, 0, core::cuda::GetStream()>>>(
76template <
typename func_t>
78 if (!device.
IsCPU()) {
79 utility::LogError(
"ParallelFor for CPU cannot run on device {}.",
86#pragma omp parallel for num_threads(utility::EstimateMaxThreads())
87 for (int64_t i = 0; i < n; ++i) {
94#if defined(SYCL_LANGUAGE_VERSION)
97template <
typename func_t>
98void ParallelForSYCL_(
const Device& device, int64_t n,
const func_t& func) {
99 if (!device.IsSYCL()) {
100 utility::LogError(
"ParallelFor for SYCL cannot run on device {}.",
106 auto queue = core::sy::SYCLContext::GetInstance().GetDefaultQueue(device);
107 size_t wg = core::sy::PreferredWorkGroupSize(device);
108 const size_t global_size = ((
static_cast<size_t>(n) + wg - 1) / wg) * wg;
109 sycl::nd_range<1> nd_range{sycl::range<1>(global_size), sycl::range<1>(wg)};
110 queue.parallel_for(nd_range, [=](sycl::nd_item<1> item) {
111 int64_t i = item.get_global_id(0);
134template <
typename func_t>
137 ParallelForCUDA_(device, n, func);
138#elif defined(SYCL_LANGUAGE_VERSION)
140 ParallelForSYCL_(device, n, func);
195template <
typename vec_func_t,
typename func_t>
199 const vec_func_t& vec_func) {
200#ifdef BUILD_ISPC_MODULE
203 ParallelForCUDA_(device, n, func);
204#elif defined(SYCL_LANGUAGE_VERSION)
206 ParallelForSYCL_(device, n, func);
210 int64_t start = n * i / num_threads;
211 int64_t end = std::min<int64_t>(n * (i + 1) / num_threads, n);
212 vec_func(start, end);
218 int64_t start = n * i / num_threads;
219 int64_t end = std::min<int64_t>(n * (i + 1) / num_threads, n);
220 vec_func(start, end);
227 ParallelForCUDA_(device, n, func);
228#elif defined(SYCL_LANGUAGE_VERSION)
230 ParallelForSYCL_(device, n, func);
241#ifdef BUILD_ISPC_MODULE
244#define OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, ...) \
245 using namespace ispc; \
246 ISPCKernel(start, end, __VA_ARGS__);
251#define OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, ...) \
253 "ISPC module disabled. Unable to call vectorized kernel {}", \
254 OPEN3D_STRINGIFY(ISPCKernel));
259#define OPEN3D_OVERLOADED_LAMBDA_(T, ISPCKernel, ...) \
260 [&](T, int64_t start, int64_t end) { \
261 OPEN3D_CALL_ISPC_KERNEL_( \
262 OPEN3D_CONCAT(ISPCKernel, OPEN3D_CONCAT(_, T)), start, end, \
275#define OPEN3D_VECTORIZED(ISPCKernel, ...) \
276 [&](int64_t start, int64_t end) { \
277 OPEN3D_CALL_ISPC_KERNEL_(ISPCKernel, start, end, __VA_ARGS__); \
293#define OPEN3D_TEMPLATE_VECTORIZED(T, ISPCKernel, ...) \
294 [&](int64_t start, int64_t end) { \
295 static_assert(std::is_arithmetic<T>::value, \
296 "Data type is not an arithmetic type"); \
298 OPEN3D_OVERLOADED_LAMBDA_(bool, ISPCKernel, __VA_ARGS__), \
299 OPEN3D_OVERLOADED_LAMBDA_(uint8_t, ISPCKernel, __VA_ARGS__), \
300 OPEN3D_OVERLOADED_LAMBDA_(int8_t, ISPCKernel, __VA_ARGS__), \
301 OPEN3D_OVERLOADED_LAMBDA_(uint16_t, ISPCKernel, __VA_ARGS__), \
302 OPEN3D_OVERLOADED_LAMBDA_(int16_t, ISPCKernel, __VA_ARGS__), \
303 OPEN3D_OVERLOADED_LAMBDA_(uint32_t, ISPCKernel, __VA_ARGS__), \
304 OPEN3D_OVERLOADED_LAMBDA_(int32_t, ISPCKernel, __VA_ARGS__), \
305 OPEN3D_OVERLOADED_LAMBDA_(uint64_t, ISPCKernel, __VA_ARGS__), \
306 OPEN3D_OVERLOADED_LAMBDA_(int64_t, ISPCKernel, __VA_ARGS__), \
307 OPEN3D_OVERLOADED_LAMBDA_(float, ISPCKernel, __VA_ARGS__), \
308 OPEN3D_OVERLOADED_LAMBDA_(double, ISPCKernel, __VA_ARGS__), \
309 [&](auto&& generic, int64_t start, int64_t end) { \
311 "Unsupported data type {} for calling " \
312 "vectorized kernel {}", \
313 typeid(generic).name(), \
314 OPEN3D_STRINGIFY(ISPCKernel)); \
315 })(T{}, start, end); \
#define OPEN3D_GET_LAST_CUDA_ERROR(message)
Definition CUDAUtils.h:47
sycl::queue queue
Definition SYCLContext.cpp:51
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
void ParallelForCPU_(const Device &device, int64_t n, const func_t &func)
Run a function in parallel on CPU.
Definition ParallelFor.h:77
void ParallelFor(const Device &device, int64_t n, const func_t &func)
Definition ParallelFor.h:135
int EstimateMaxThreads()
Estimate the maximum number of threads to be used in a parallel region.
Definition Parallel.cpp:31
Definition PinholeCameraIntrinsic.cpp:16