39#if defined(SYCL_LANGUAGE_VERSION)
40#include <sycl/sycl.hpp>
43#if defined(__HIP_DEVICE_COMPILE__)
44#include "hip/hip_runtime.h"
56#include "cs_math_cuda.cuh"
78#if defined(SYCL_LANGUAGE_VERSION)
80#define CS_DISPATCH_REDUCER_TYPE(type) auto
84#define CS_DISPATCH_REDUCER_TYPE(type) type
109template <
class Derived>
115 template <
class F,
class... Args>
120 template <
class M,
class F,
class... Args>
127 template <
class M,
class F,
class... Args>
135 template <
class T,
class F,
class... Args>
142 template <
class T,
class R,
class F,
class... Args>
145 (
cs_lnum_t n, T& r, R& reducer, F&& f, Args&&... args) =
delete;
149 template <
class... Args>
170template <
class Derived>
171template <
class M,
class F,
class... Args>
173 (
const M* m, F&& f, Args&&... args) {
177 static_cast<Args&&
>(args)...);
181template <
class Derived>
182template <
class M,
class F,
class... Args>
184 (
const M* m, F&& f, Args&&... args) {
188 static_cast<Args&&
>(args)...);
192template <
class Derived>
195 ([[maybe_unused]]
const M* m,
202template <
class Derived>
205 ([[maybe_unused]]
const M* m,
225 : n_min_per_thread(
CS_THR_MIN), n_threads_(-1)
237#if defined(HAVE_OPENMP)
243 int n_t = n_threads_;
246 int n_t_l = n / n_min_per_thread;
260 [[maybe_unused]]
size_t type_size,
264#if defined(HAVE_OPENMP)
265 const int t_id = omp_get_thread_num();
266 const int n_t = omp_get_num_threads();
267 const cs_lnum_t t_n = (n + n_t - 1) / n_t;
271 e_id = (t_id+1) * t_n;
274 if (e_id > n) e_id = n;
286 this->n_min_per_thread = n;
292 return this->n_min_per_thread;
298 this->n_threads_ = n;
304 return this->n_threads_;
308 template <
class F,
class... Args>
312 #pragma omp parallel for num_threads(n_threads(n))
322 template <
class M,
class F,
class... Args>
325 const int n_i_groups = m->i_face_numbering->n_groups;
326 const int n_i_threads = m->i_face_numbering->n_threads;
328 for (
int g_id = 0; g_id < n_i_groups; g_id++) {
330 #pragma omp parallel for
332 for (
int t_id = 0; t_id < n_i_threads; t_id++) {
333 for (
cs_lnum_t f_id = i_group_index[(t_id * n_i_groups + g_id) * 2];
334 f_id < i_group_index[(t_id * n_i_groups + g_id) * 2 + 1];
345 template <
class M,
class F,
class... Args>
348 const int n_b_groups = m->b_face_numbering->n_groups;
349 const int n_b_threads = m->b_face_numbering->n_threads;
351 for (
int g_id = 0; g_id < n_b_groups; g_id++) {
353 #pragma omp parallel for
355 for (
int t_id = 0; t_id < n_b_threads; t_id++) {
356 for (
cs_lnum_t f_id = b_group_index[(t_id * n_b_groups + g_id) * 2];
357 f_id < b_group_index[(t_id * n_b_groups + g_id) * 2 + 1];
367 template <
class T,
class F,
class... Args>
377 #pragma omp parallel for reduction(+:sum) num_threads(n_threads(n))
384 #pragma omp parallel num_threads(n_threads(n))
388 thread_range(n, 4, s_id, e_id);
394 cs_lnum_t n_blocks = (_n + block_size - 1) / block_size;
395 n_sblocks = (n_blocks > 1) ? std::sqrt(n_blocks) : 1;
397 blocks_in_sblocks = (_n + n_b - 1) / n_b;
400 for (
cs_lnum_t sid = 0; sid < n_sblocks; sid++) {
403 for (
cs_lnum_t bid = 0; bid < blocks_in_sblocks; bid++) {
404 cs_lnum_t start_id = block_size * (blocks_in_sblocks*sid + bid) + s_id;
405 cs_lnum_t end_id = start_id + block_size;
409 for (
cs_lnum_t i = start_id; i < end_id; i++) {
410 f(i, sum_block, args...);
412 sum_sblock += sum_block;
429 template <
class T,
class R,
class F,
class... Args>
436 reducer.identity(result);
439 #pragma omp parallel num_threads(n_threads(n))
443 thread_range(n, 4, s_id, e_id);
449 cs_lnum_t n_blocks = (_n + block_size - 1) / block_size;
450 n_sblocks = (n_blocks > 1) ? std::sqrt(n_blocks) : 1;
452 blocks_in_sblocks = (_n + n_b - 1) / n_b;
455 for (
cs_lnum_t sid = 0; sid < n_sblocks; sid++) {
457 reducer.identity(result_sblock);
459 for (
cs_lnum_t bid = 0; bid < blocks_in_sblocks; bid++) {
460 cs_lnum_t start_id = block_size * (blocks_in_sblocks*sid + bid) + s_id;
461 cs_lnum_t end_id = start_id + block_size;
465 reducer.identity(result_block);
466 for (
cs_lnum_t i = start_id; i < end_id; i++) {
467 f(i, result_block, args...);
468 reducer.combine(result_sblock, result_block);
476 reducer.combine(result, result_sblock);
486 template <
class... Args>
512#if defined(__CUDACC__)
520template <
class F,
class... Args>
521__global__
void cs_cuda_kernel_parallel_for(
cs_lnum_t n, F f, Args... args) {
523 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
524 id += blockDim.x * gridDim.x) {
536template <
class T,
class F,
class... Args>
538cs_cuda_kernel_parallel_for_reduce_sum(
cs_lnum_t n,
543 extern __shared__
int p_stmp[];
544 T *stmp =
reinterpret_cast<T *
>(p_stmp);
549 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
550 id += blockDim.x * gridDim.x) {
551 f(
id, stmp[tid], args...);
554 switch (blockDim.x) {
556 cs_cuda_reduce_block_reduce_sum<1024, 1>(stmp, tid, b_res);
559 cs_cuda_reduce_block_reduce_sum<512, 1>(stmp, tid, b_res);
562 cs_cuda_reduce_block_reduce_sum<256, 1>(stmp, tid, b_res);
565 cs_cuda_reduce_block_reduce_sum<128, 1>(stmp, tid, b_res);
579template <
class T,
class R,
class F,
class... Args>
581cs_cuda_kernel_parallel_for_reduce(
cs_lnum_t n,
587 extern __shared__
int p_stmp[];
588 T *stmp =
reinterpret_cast<T *
>(p_stmp);
591 reducer.identity(stmp[tid]);
593 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
594 id += blockDim.x * gridDim.x) {
605 switch (blockDim.x) {
607 cs_cuda_reduce_block_reduce<1024, R>(stmp, tid, b_res);
610 cs_cuda_reduce_block_reduce<512, R>(stmp, tid, b_res);
613 cs_cuda_reduce_block_reduce<256, R>(stmp, tid, b_res);
616 cs_cuda_reduce_block_reduce<128, R>(stmp, tid, b_res);
635 cudaStream_t stream_;
644 cs_device_context(
void)
645 : grid_size_(0), block_size_(256), stream_(cs_cuda_get_stream(0)),
646 device_(0), use_gpu_(true)
648 device_ = cs_glob_cuda_device_id;
651 cs_device_context(
long grid_size,
655 : grid_size_(grid_size), block_size_(block_size), stream_(stream),
656 device_(
device), use_gpu_(true)
659 cs_device_context(
long grid_size,
662 : grid_size_(grid_size), block_size_(block_size), stream_(stream),
663 device_(0), use_gpu_(true)
665 device_ = cs_base_cuda_get_device();
668 cs_device_context(
long grid_size,
670 : grid_size_(grid_size), block_size_(block_size),
671 stream_(cs_cuda_get_stream(0)), device_(0), use_gpu_(true)
673 device_ = cs_base_cuda_get_device();
676 cs_device_context(cudaStream_t stream)
677 : grid_size_(0), block_size_(256), stream_(stream), device_(0),
680 device_ = cs_base_cuda_get_device();
690 cs_device_context(cs_device_context
const &) =
default;
692 cs_device_context(cs_device_context &&) =
default;
695 operator = (cs_device_context
const &) =
default;
698 operator = (cs_device_context &&) =
default;
708 set_cuda_grid(
long grid_size,
710 this->grid_size_ = (grid_size > 0) ? grid_size : -1;
711 this->block_size_ = block_size;
717 set_stream(cudaStream_t stream) {
718 this->stream_ = stream;
724 set_stream(
int stream_id) {
725 this->stream_ = cs_cuda_get_stream(stream_id);
732 return this->stream_;
738 set_cuda_device(
int device) {
745 set_use_gpu(
bool use_gpu) {
746 this->use_gpu_ = use_gpu;
753 return (device_ >= 0 && use_gpu_);
766 alloc_mode(
bool readable_on_cpu) {
768 if (device_ >= 0 && use_gpu_) {
780 template <
class F,
class... Args>
783 if (device_ < 0 || use_gpu_ ==
false) {
787 long l_grid_size = grid_size_;
788 if (l_grid_size < 1) {
789 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
793 cs_cuda_kernel_parallel_for<<<l_grid_size, block_size_, 0, stream_>>>
794 (n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
796#if defined(DEBUG) || !defined(NDEBUG)
797 cudaError_t retcode = cudaGetLastError();
798 if (retcode != cudaSuccess)
800 "[CUDA error] %d: %s\n"
801 "with grid size %ld, block size %ld.",
802 retcode, ::cudaGetErrorString(retcode),
803 l_grid_size, block_size_);
810 template <
class M,
class F,
class... Args>
814 if (device_ < 0 || use_gpu_ ==
false) {
818 long l_grid_size = grid_size_;
819 if (l_grid_size < 1) {
820 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
824 cs_cuda_kernel_parallel_for<<<l_grid_size, block_size_, 0, stream_>>>
825 (n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
832 template <
class T,
class F,
class... Args>
838 if (device_ < 0 || use_gpu_ ==
false) {
844 long l_grid_size = grid_size_;
845 if (l_grid_size < 1) {
846 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
852 int stream_id = cs_cuda_get_stream_id(stream_);
856 T *r_grid_, *r_reduce_, *r_host_;
857 cs_cuda_get_2_stage_reduce_buffers
858 (stream_id, n,
sizeof(
sum), l_grid_size,
859 (
void *&)r_grid_, (
void *&)r_reduce_, (
void *&)r_host_);
861 int smem_size = block_size_ *
sizeof(T);
862 cs_cuda_kernel_parallel_for_reduce_sum
863 <<<l_grid_size, block_size_, smem_size, stream_>>>
864 (n, r_grid_,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
866#if defined(DEBUG) || !defined(NDEBUG)
867 cudaError_t retcode = cudaGetLastError();
868 if (retcode != cudaSuccess)
870 "[CUDA error] %d: %s\n"
871 "with grid size %ld, block size %ld, shared memory size %d.",
872 retcode, ::cudaGetErrorString(retcode),
873 l_grid_size, block_size_, smem_size);
876 switch (block_size_) {
878 cs_cuda_reduce_sum_single_block<1024, 1>
879 <<<1, block_size_, 0, stream_>>>
880 (l_grid_size, r_grid_, r_reduce_);
883 cs_cuda_reduce_sum_single_block<512, 1>
884 <<<1, block_size_, 0, stream_>>>
885 (l_grid_size, r_grid_, r_reduce_);
888 cs_cuda_reduce_sum_single_block<256, 1>
889 <<<1, block_size_, 0, stream_>>>
890 (l_grid_size, r_grid_, r_reduce_);
893 cs_cuda_reduce_sum_single_block<128, 1>
894 <<<1, block_size_, 0, stream_>>>
895 (l_grid_size, r_grid_, r_reduce_);
901 CS_CUDA_CHECK(cudaMemcpyAsync(r_host_, r_reduce_,
sizeof(
sum),
902 cudaMemcpyDeviceToHost, stream_));
904#if defined(DEBUG) || !defined(NDEBUG)
905 retcode = cudaGetLastError();
906 if (retcode != cudaSuccess)
908 "[CUDA error] %d: %s\n"
909 "with grid size %ld, block size %ld, shared memory size %d.",
910 retcode, ::cudaGetErrorString(retcode),
911 l_grid_size, block_size_, (
int)smem_size);
914 CS_CUDA_CHECK(cudaStreamSynchronize(stream_));
915 CS_CUDA_CHECK(cudaGetLastError());
922 template <
class T,
class R,
class F,
class... Args>
929 if (device_ < 0 || use_gpu_ ==
false) {
933 reducer.identity(result);
935 long l_grid_size = grid_size_;
936 if (l_grid_size < 1) {
937 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
943 int stream_id = cs_cuda_get_stream_id(stream_);
947 T *r_grid_, *r_reduce_, *r_host_;
948 cs_cuda_get_2_stage_reduce_buffers
949 (stream_id, n,
sizeof(result), l_grid_size,
950 (
void *&)r_grid_, (
void *&)r_reduce_, (
void *&)r_host_);
952 int l_block_size = block_size_;
953 int smem_size = l_block_size *
sizeof(T);
954 while (smem_size > cs_glob_cuda_shared_mem_per_block) {
957 if (l_block_size < 2)
959 "Type of size %d exceeds capacity of "
960 "CUDA shared memory (%d).",
961 (
int)
sizeof(T), cs_glob_cuda_shared_mem_per_block);
963 smem_size = l_block_size *
sizeof(T);
966#if defined(DEBUG) || !defined(NDEBUG)
967 cudaError_t retcode = cudaSuccess;
970 cs_cuda_kernel_parallel_for_reduce<T, R>
971 <<<l_grid_size, l_block_size, smem_size, stream_>>>
972 (n, r_grid_, reducer,
static_cast<F&&
>(f),
973 static_cast<Args&&
>(args)...);
975#if defined(DEBUG) || !defined(NDEBUG)
976 retcode = cudaGetLastError();
977 if (retcode != cudaSuccess)
979 "[CUDA error] %d: %s\n"
980 "with grid size %ld, block size %d, shared memory size %d.",
981 retcode, ::cudaGetErrorString(retcode),
982 l_grid_size, l_block_size, smem_size);
985 switch (l_block_size) {
987 cs_cuda_reduce_single_block<1024, R>
988 <<<1, l_block_size, smem_size, stream_>>>
989 (l_grid_size, r_grid_, r_reduce_);
992 cs_cuda_reduce_single_block<512, R>
993 <<<1, l_block_size, smem_size, stream_>>>
994 (l_grid_size, r_grid_, r_reduce_);
997 cs_cuda_reduce_single_block<256, R>
998 <<<1, l_block_size, smem_size, stream_>>>
999 (l_grid_size, r_grid_, r_reduce_);
1002 cs_cuda_reduce_single_block<128, R>
1003 <<<1, l_block_size, smem_size, stream_>>>
1004 (l_grid_size, r_grid_, r_reduce_);
1010#if defined(DEBUG) || !defined(NDEBUG)
1011 retcode = cudaGetLastError();
1012 if (retcode != cudaSuccess)
1014 "[CUDA error] %d: %s\n"
1015 "with grid size %ld, block size %d, shared memory size %d.",
1016 retcode, ::cudaGetErrorString(retcode),
1017 l_grid_size, l_block_size, (
int)smem_size);
1020 CS_CUDA_CHECK(cudaMemcpyAsync(r_host_, r_reduce_,
sizeof(result),
1021 cudaMemcpyDeviceToHost, stream_));
1023 CS_CUDA_CHECK(cudaStreamSynchronize(stream_));
1024 CS_CUDA_CHECK(cudaGetLastError());
1025 result = r_host_[0];
1031 template <
class... Args>
1034 if (device_ > -1 && use_gpu_) {
1035 CS_CUDA_CHECK(cudaStreamSynchronize(stream_));
1036 CS_CUDA_CHECK(cudaGetLastError());
1047 if (device_ < 0 || use_gpu_ ==
false) {
1060 if (device_ < 0 || use_gpu_ ==
false) {
1070#elif defined(__HIPCC__)
1078template <
class F,
class... Args>
1079__global__
void cs_hip_kernel_parallel_for(
cs_lnum_t n, F f, Args... args) {
1081 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
1082 id += blockDim.x * gridDim.x) {
1094template <
class T,
class F,
class... Args>
1096cs_hip_kernel_parallel_for_reduce_sum(
cs_lnum_t n,
1101 extern __shared__
int p_stmp[];
1102 T *stmp =
reinterpret_cast<T *
>(p_stmp);
1107 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
1108 id += blockDim.x * gridDim.x) {
1109 f(
id, stmp[tid], args...);
1112 switch (blockDim.x) {
1114 cs_hip_reduce_block_reduce_sum<1024, 1>(stmp, tid, b_res);
1117 cs_hip_reduce_block_reduce_sum<512, 1>(stmp, tid, b_res);
1120 cs_hip_reduce_block_reduce_sum<256, 1>(stmp, tid, b_res);
1123 cs_hip_reduce_block_reduce_sum<128, 1>(stmp, tid, b_res);
1137template <
class T,
class R,
class F,
class... Args>
1139cs_hip_kernel_parallel_for_reduce(
cs_lnum_t n,
1145 extern __shared__
int p_stmp[];
1146 T *stmp =
reinterpret_cast<T *
>(p_stmp);
1149 reducer.identity(stmp[tid]);
1151 for (
cs_lnum_t id = blockIdx.x * blockDim.x + threadIdx.x;
id < n;
1152 id += blockDim.x * gridDim.x) {
1163 switch (blockDim.x) {
1165 cs_hip_reduce_block_reduce<1024, R>(stmp, tid, b_res);
1168 cs_hip_reduce_block_reduce<512, R>(stmp, tid, b_res);
1171 cs_hip_reduce_block_reduce<256, R>(stmp, tid, b_res);
1174 cs_hip_reduce_block_reduce<128, R>(stmp, tid, b_res);
1193 hipStream_t stream_;
1202 cs_device_context(
void)
1203 : grid_size_(0), block_size_(256), stream_(cs_hip_get_stream(0)),
1204 device_(0), use_gpu_(true)
1206 device_ = cs_glob_hip_device_id;
1209 cs_device_context(
long grid_size,
1213 : grid_size_(grid_size), block_size_(block_size), stream_(stream),
1214 device_(
device), use_gpu_(true)
1217 cs_device_context(
long grid_size,
1220 : grid_size_(grid_size), block_size_(block_size), stream_(stream),
1221 device_(0), use_gpu_(true)
1226 cs_device_context(
long grid_size,
1228 : grid_size_(grid_size), block_size_(block_size),
1229 stream_(cs_hip_get_stream(0)), device_(0), use_gpu_(true)
1234 cs_device_context(hipStream_t stream)
1235 : grid_size_(0), block_size_(256), stream_(stream), device_(0),
1248 cs_device_context(cs_device_context
const &) =
default;
1250 cs_device_context(cs_device_context &&) =
default;
1253 operator = (cs_device_context
const &) =
default;
1256 operator = (cs_device_context &&) =
default;
1266 set_hip_grid(
long grid_size,
1268 this->grid_size_ = (grid_size > 0) ? grid_size : -1;
1269 this->block_size_ = block_size;
1275 set_stream(hipStream_t stream) {
1276 this->stream_ = stream;
1282 set_stream(
int stream_id) {
1283 this->stream_ = cs_hip_get_stream(stream_id);
1291 set_hip_device(
int device) {
1298 set_use_gpu(
bool use_gpu) {
1299 this->use_gpu_ = use_gpu;
1306 return (device_ >= 0 && use_gpu_);
1319 alloc_mode(
bool readable_on_cpu) {
1321 if (device_ >= 0 && use_gpu_) {
1322 if (readable_on_cpu)
1333 template <
class F,
class... Args>
1336 if (device_ < 0 || use_gpu_ ==
false) {
1340 long l_grid_size = grid_size_;
1341 if (l_grid_size < 1) {
1342 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
1346 cs_hip_kernel_parallel_for<<<l_grid_size, block_size_, 0, stream_>>>
1347 (n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
1353 template <
class M,
class F,
class... Args>
1357 if (device_ < 0 || use_gpu_ ==
false) {
1361 long l_grid_size = grid_size_;
1362 if (l_grid_size < 1) {
1363 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
1367 cs_hip_kernel_parallel_for<<<l_grid_size, block_size_, 0, stream_>>>
1368 (n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
1375 template <
class T,
class F,
class... Args>
1381 if (device_ < 0 || use_gpu_ ==
false) {
1387 long l_grid_size = grid_size_;
1388 if (l_grid_size < 1) {
1389 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
1395 int stream_id = cs_hip_get_stream_id(stream_);
1399 T *r_grid_, *r_reduce_, *r_host_;
1400 cs_hip_get_2_stage_reduce_buffers
1401 (stream_id, n,
sizeof(
sum), l_grid_size,
1402 (
void *&)r_grid_, (
void *&)r_reduce_, (
void *&)r_host_);
1404 int smem_size = block_size_ *
sizeof(T);
1405 cs_hip_kernel_parallel_for_reduce_sum
1406 <<<l_grid_size, block_size_, smem_size, stream_>>>
1407 (n, r_grid_,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
1409#if defined(DEBUG) || !defined(NDEBUG)
1410 hipError_t retcode = hipGetLastError();
1411 if (retcode != hipSuccess)
1413 "[HIP error] %d: %s\n"
1414 "with grid size %ld, block size %ld, shared memory size %d.",
1415 retcode, ::hipGetErrorString(retcode),
1416 l_grid_size, block_size_, smem_size);
1419 switch (block_size_) {
1421 cs_hip_reduce_sum_single_block<1024, 1>
1422 <<<1, block_size_, 0, stream_>>>
1423 (l_grid_size, r_grid_, r_reduce_);
1426 cs_hip_reduce_sum_single_block<512, 1>
1427 <<<1, block_size_, 0, stream_>>>
1428 (l_grid_size, r_grid_, r_reduce_);
1431 cs_hip_reduce_sum_single_block<256, 1>
1432 <<<1, block_size_, 0, stream_>>>
1433 (l_grid_size, r_grid_, r_reduce_);
1436 cs_hip_reduce_sum_single_block<128, 1>
1437 <<<1, block_size_, 0, stream_>>>
1438 (l_grid_size, r_grid_, r_reduce_);
1444 CS_HIP_CHECK(hipMemcpyAsync(r_host_, r_reduce_,
sizeof(
sum),
1445 hipMemcpyDeviceToHost, stream_));
1447#if defined(DEBUG) || !defined(NDEBUG)
1448 retcode = hipGetLastError();
1449 if (retcode != hipSuccess)
1451 "[HIP error] %d: %s\n"
1452 "with grid size %ld, block size %ld, shared memory size %d.",
1453 retcode, ::hipGetErrorString(retcode),
1454 l_grid_size, block_size_, (
int)smem_size);
1457 CS_HIP_CHECK(hipStreamSynchronize(stream_));
1458 CS_HIP_CHECK(hipGetLastError());
1465 template <
class T,
class R,
class F,
class... Args>
1472 if (device_ < 0 || use_gpu_ ==
false) {
1476 reducer.identity(result);
1478 long l_grid_size = grid_size_;
1479 if (l_grid_size < 1) {
1480 l_grid_size = (n % block_size_) ? n/block_size_ + 1 : n/block_size_;
1486 int stream_id = cs_hip_get_stream_id(stream_);
1490 T *r_grid_, *r_reduce_, *r_host_;
1491 cs_hip_get_2_stage_reduce_buffers
1492 (stream_id, n,
sizeof(result), l_grid_size,
1493 (
void *&)r_grid_, (
void *&)r_reduce_, (
void *&)r_host_);
1495 int l_block_size = block_size_;
1496 int smem_size = l_block_size *
sizeof(T);
1497 while (smem_size > cs_glob_hip_shared_mem_per_block) {
1500 if (l_block_size < 2)
1502 "Type of size %d exceeds capacity of "
1503 "HIP shared memory (%d).",
1504 (
int)
sizeof(T), cs_glob_hip_shared_mem_per_block);
1506 smem_size = l_block_size *
sizeof(T);
1509#if defined(DEBUG) || !defined(NDEBUG)
1510 hipError_t retcode = hipSuccess;
1513 cs_hip_kernel_parallel_for_reduce<T, R>
1514 <<<l_grid_size, l_block_size, smem_size, stream_>>>
1515 (n, r_grid_, reducer,
static_cast<F&&
>(f),
1516 static_cast<Args&&
>(args)...);
1518#if defined(DEBUG) || !defined(NDEBUG)
1519 retcode = hipGetLastError();
1520 if (retcode != hipSuccess)
1522 "[HIP error] %d: %s\n"
1523 "with grid size %ld, block size %d, shared memory size %d.",
1524 retcode, ::hipGetErrorString(retcode),
1525 l_grid_size, l_block_size, smem_size);
1528 switch (l_block_size) {
1530 cs_hip_reduce_single_block<1024, R>
1531 <<<1, l_block_size, smem_size, stream_>>>
1532 (l_grid_size, r_grid_, r_reduce_);
1535 cs_hip_reduce_single_block<512, R>
1536 <<<1, l_block_size, smem_size, stream_>>>
1537 (l_grid_size, r_grid_, r_reduce_);
1540 cs_hip_reduce_single_block<256, R>
1541 <<<1, l_block_size, smem_size, stream_>>>
1542 (l_grid_size, r_grid_, r_reduce_);
1545 cs_hip_reduce_single_block<128, R>
1546 <<<1, l_block_size, smem_size, stream_>>>
1547 (l_grid_size, r_grid_, r_reduce_);
1553#if defined(DEBUG) || !defined(NDEBUG)
1554 retcode = hipGetLastError();
1555 if (retcode != hipSuccess)
1557 "[HIP error] %d: %s\n"
1558 "with grid size %ld, block size %d, shared memory size %d.",
1559 retcode, ::hipGetErrorString(retcode),
1560 l_grid_size, l_block_size, (
int)smem_size);
1563 CS_HIP_CHECK(hipMemcpyAsync(r_host_, r_reduce_,
sizeof(result),
1564 hipMemcpyDeviceToHost, stream_));
1566 CS_HIP_CHECK(hipStreamSynchronize(stream_));
1567 CS_HIP_CHECK(hipGetLastError());
1568 result = r_host_[0];
1574 template <
class... Args>
1577 if (device_ > -1 && use_gpu_) {
1578 CS_HIP_CHECK(hipStreamSynchronize(stream_));
1579 CS_HIP_CHECK(hipGetLastError());
1590 if (device_ < 0 || use_gpu_ ==
false) {
1603 if (device_ < 0 || use_gpu_ ==
false) {
1613#elif defined(SYCL_LANGUAGE_VERSION)
1616#if !defined(CS_GLOB_SYCL_QUEUE_IS_DEFINED)
1617extern sycl::queue cs_glob_sycl_queue;
1618#define CS_GLOB_SYCL_QUEUE_IS_DEFINED 1
1629 sycl::queue &queue_;
1638 cs_device_context(
void)
1639 : queue_(cs_glob_sycl_queue), is_gpu(false), use_gpu_(true)
1641 is_gpu = queue_.get_device().is_gpu();
1647 set_use_gpu(
bool use_gpu) {
1648 this->use_gpu_ = use_gpu;
1655 return (is_gpu && use_gpu_);
1668 alloc_mode([[maybe_unused]]
bool readable_on_cpu) {
1677 template <
class F,
class... Args>
1680 if (is_gpu ==
false || use_gpu_ ==
false) {
1684 queue_.parallel_for(n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
1690 template <
class M,
class F,
class... Args>
1694 if (is_gpu ==
false || use_gpu_ ==
false) {
1698 queue_.parallel_for(n,
static_cast<F&&
>(f),
static_cast<Args&&
>(args)...);
1704 template <
class T,
class F,
class... Args>
1710 if (is_gpu ==
false || use_gpu_ ==
false) {
1718 T *sum_ptr = (T *)sycl::malloc_shared(
sizeof(T), queue_);
1720 queue_.parallel_for(n,
1721 sycl::reduction(sum_ptr, (T)0, sycl::plus<T>()),
1722 static_cast<F&&
>(f),
1723 static_cast<Args&&
>(args)...).wait();
1727 sycl::free((
void *)sum_ptr, queue_);
1733 template <
class T,
class R,
class F,
class... Args>
1746 template <
class... Args>
1749 if (is_gpu && use_gpu_) {
1761 if (is_gpu ==
false || use_gpu_ ==
false) {
1774 if (is_gpu ==
false || use_gpu_ ==
false) {
1784#elif defined(HAVE_OPENMP_TARGET)
1802 cs_device_context(
void)
1803 : is_gpu(false), use_gpu_(true)
1807 is_gpu = (omp_get_num_devices() > 1) ?
true :
false;
1813 set_use_gpu(
bool use_gpu) {
1814 this->use_gpu_ = use_gpu;
1821 return (is_gpu && use_gpu_);
1834 alloc_mode([[maybe_unused]]
bool readable_on_cpu) {
1843 template <
class F,
class... Args>
1846 if (is_gpu ==
false || use_gpu_ ==
false) {
1851# pragma omp target teams distribute parallel for
1860 template <
class T,
class F,
class... Args>
1866 if (is_gpu ==
false || use_gpu_ ==
false) {
1872# pragma omp target teams distribute parallel for reduction(+:sum)
1881 template <
class T,
class R,
class F,
class... Args>
1894 template <
class... Args>
1905 if (is_gpu ==
false || use_gpu_ ==
false) {
1918 if (is_gpu ==
false || use_gpu_ ==
false) {
1950#if !defined(__CUDACC__) && !defined(__HIPCC__)
1958#if !defined(__CUDACC__)
1962 [[maybe_unused]]
long block_size) {
1971#if !defined(__HIPCC__)
1975 [[maybe_unused]]
long block_size) {
1984#if !defined(__CUDACC__) \
1985 && !defined(__HIPCC__) \
1986 && !defined(SYCL_LANGUAGE_VERSION) \
1987 && !defined(HAVE_OPENMP_TARGET)
2019 template <
class F,
class... Args>
2021 [[maybe_unused]] F&& f,
2022 [[maybe_unused]] Args&&... args) {
2028 template <
class T,
class F,
class... Args>
2030 [[maybe_unused]] T&
sum,
2031 [[maybe_unused]] F&& f,
2032 [[maybe_unused]] Args&&... args) {
2038 template <
class T,
class R,
class F,
class... Args>
2040 [[maybe_unused]] T& result,
2041 [[maybe_unused]] R& reducer,
2042 [[maybe_unused]] F&& f,
2043 [[maybe_unused]] Args&&... args) {
2049 template <
class... Args>
2063template <
class... Contexts>
2066 public Contexts... {
2074 : Contexts(std::move(contexts))...
2098 template <
class M,
class F,
class... Args>
2100 bool launched =
false;
2101 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2102 ( launched = launched
2126 template <
class M,
class F,
class... Args>
2128 bool launched =
false;
2129 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2130 ( launched = launched
2131 || Contexts::parallel_for_b_faces(m, f, args...),
nullptr)...
2145 template <
class F,
class... Args>
2147 bool launched =
false;
2148 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2149 ( launched = launched
2167 template <
class T,
class F,
class... Args>
2170 bool launched =
false;
2171 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2172 ( launched = launched
2193 template <
class T,
class R,
class F,
class... Args>
2195 (
cs_lnum_t n, T& result, R& reducer, F&& f, Args&&... args) {
2196 bool launched =
false;
2197 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2198 ( launched = launched
2213 [[maybe_unused]]
decltype(
nullptr) try_execute[] = {
2236 [[maybe_unused]]
decltype(
nullptr) try_query[] = {
2238 || Contexts::try_get_parallel_for_i_faces_sum_type(m, sum_type),
2261 [[maybe_unused]]
decltype(
nullptr) try_query[] = {
2263 || Contexts::try_get_parallel_for_b_faces_sum_type(m, sum_type),
2279#if defined(__CUDACC__) \
2280 || defined(__HIPCC__) \
2281 || defined(SYCL_LANGUAGE_VERSION) \
2282 || defined(HAVE_OPENMP_TARGET)
2292#if defined(__CUDACC__) \
2293 || defined(__HIPCC__) \
2294 || defined(SYCL_LANGUAGE_VERSION) \
2295 || defined(HAVE_OPENMP_TARGET)
2303 using base_t::base_t;
2304 using base_t::operator=;
2351template <
typename T>
2352__device__
static void __forceinline__
2363 sum_v::ref(*dest).conflict_free_add(-1u, v);
2365 atomicAdd(dest, src);
2373#elif defined(__HIP_DEVICE_COMPILE__)
2375template <
typename T>
2376__device__
static void __forceinline__
2382 atomicAdd(dest, src);
2389#elif defined(SYCL_LANGUAGE_VERSION)
2391template <
typename T>
2402 sycl::memory_order::relaxed,
2403 sycl::memory_scope::device> aref(*dest);
2404 aref.fetch_add(src);
2410template <
typename T>
2447template <
size_t dim,
typename T>
2448__device__
static void __forceinline__
2459#if __CUDA_ARCH__ >= 700
2463 for (
size_t i = 0; i < dim; i++) {
2464 v[i].
get() = src[i];
2467 sum_v &vs =
reinterpret_cast<sum_v &
>(*dest);
2468 vs.conflict_free_add(-1u, v);
2472 for (
size_t i = 0; i < dim; i++) {
2473 atomicAdd(&dest[i], src[i]);
2479#elif defined(__HIP_DEVICE_COMPILE__)
2481template <
size_t dim,
typename T>
2482__device__
static void __forceinline__
2493 for (
size_t i = 0; i < dim; i++) {
2494 atomicAdd(&dest[i], src[i]);
2499#elif defined(SYCL_LANGUAGE_VERSION)
2501template <
size_t dim,
typename T>
2508 for (
size_t i = 0; i < dim; i++) {
2513 for (
size_t i = 0; i < dim; i++) {
2515 sycl::memory_order::relaxed,
2516 sycl::memory_scope::device> aref(dest[i]);
2517 aref.fetch_add(src[i]);
2524template <
size_t dim,
typename T>
2531 for (
size_t i = 0; i < dim; i++) {
2536 for (
size_t i = 0; i < dim; i++) {
void bft_error(const char *const file_name, const int line_num, const int sys_error_code, const char *const format,...)
Calls the error handler (set by bft_error_handler_set() or default).
Definition: bft_error.cpp:187
Class for value assembly using warp-based partial summation to reduce conflict occurences in downstre...
Definition: cs_math_hip.h:172
__device__ inner_type & get() noexcept
Definition: cs_math_hip.h:273
Definition: cs_dispatch.h:2066
cs_combined_context()=default
auto parallel_for_reduce_sum(cs_lnum_t n, T &sum, F &&f, Args &&... args)
Definition: cs_dispatch.h:2169
cs_combined_context(Contexts... contexts)
Definition: cs_dispatch.h:2073
auto parallel_for_reduce(cs_lnum_t n, T &result, R &reducer, F &&f, Args &&... args)
Definition: cs_dispatch.h:2195
auto parallel_for_b_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:2127
auto parallel_for_i_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:2099
auto parallel_for(cs_lnum_t n, F &&f, Args &&... args)
Definition: cs_dispatch.h:2146
void wait(void)
Wait (synchronize) until launched computations have finished.
Definition: cs_dispatch.h:2211
cs_dispatch_sum_type_t get_parallel_for_b_faces_sum_type(const M *m)
Return sum type to be used with parallel_for_b_faces.
Definition: cs_dispatch.h:2258
cs_dispatch_sum_type_t get_parallel_for_i_faces_sum_type(const M *m)
Return sum type to be used with parallel_for_i_faces.
Definition: cs_dispatch.h:2233
Definition: cs_dispatch.h:110
decltype(auto) parallel_for(cs_lnum_t n, F &&f, Args &&... args)=delete
bool try_get_parallel_for_b_faces_sum_type(const M *m, cs_dispatch_sum_type_t &st)
Definition: cs_dispatch.h:205
decltype(auto) parallel_for_b_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:184
decltype(auto) parallel_for_reduce_sum(cs_lnum_t n, T &sum, F &&f, Args &&... args)=delete
bool try_get_parallel_for_i_faces_sum_type(const M *m, cs_dispatch_sum_type_t &st)
Definition: cs_dispatch.h:195
decltype(auto) wait(void)=delete
decltype(auto) parallel_for_i_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:173
decltype(auto) parallel_for_reduce(cs_lnum_t n, T &r, R &reducer, F &&f, Args &&... args)=delete
Definition: cs_dispatch.h:2288
Definition: cs_dispatch.h:215
cs_host_context()
Definition: cs_dispatch.h:224
cs_lnum_t n_min_per_cpu_thread(void)
Get minimum number of elements threshold for CPU multithread execution.
Definition: cs_dispatch.h:291
bool parallel_for(cs_lnum_t n, F &&f, Args &&... args)
Iterate using a plain omp parallel for.
Definition: cs_dispatch.h:310
bool parallel_for_reduce_sum(cs_lnum_t n, T &sum, F &&f, Args &&... args)
Plain OpenMP parallel reduction with simple sum.
Definition: cs_dispatch.h:369
void set_n_cpu_threads(int n)
Set number of threads for CPU multithread execution.
Definition: cs_dispatch.h:297
bool wait(void)
Wait upon completion.
Definition: cs_dispatch.h:488
bool try_get_parallel_for_b_faces_sum_type(const M *m, cs_dispatch_sum_type_t &st)
Definition: cs_dispatch.h:504
bool try_get_parallel_for_i_faces_sum_type(const M *m, cs_dispatch_sum_type_t &st)
Definition: cs_dispatch.h:495
bool parallel_for_b_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:347
int n_cpu_threads(void)
Get number of threads for CPU multithread execution (-1 if automatic)
Definition: cs_dispatch.h:303
bool parallel_for_i_faces(const M *m, F &&f, Args &&... args)
Definition: cs_dispatch.h:324
bool parallel_for_reduce(cs_lnum_t n, T &result, R &reducer, F &&f, Args &&... args)
OpenMP parallel reduction with general reducer.
Definition: cs_dispatch.h:431
void set_n_min_per_cpu_thread(cs_lnum_t n)
Set minimum number of elements threshold for CPU multithread execution.
Definition: cs_dispatch.h:285
Definition: cs_dispatch.h:1934
bool parallel_for(cs_lnum_t n, F &&f, Args &&... args)
Definition: cs_dispatch.h:2020
void set_cuda_device(int device_id)
Definition: cs_dispatch.h:1966
void set_hip_grid(long grid_size, long block_size)
Definition: cs_dispatch.h:1974
cs_alloc_mode_t alloc_mode(bool readable_on_cpu)
Definition: cs_dispatch.h:2010
bool parallel_for_reduce_sum(cs_lnum_t n, T &sum, F &&f, Args &&... args)
Definition: cs_dispatch.h:2029
void set_hip_device(int device_id)
Definition: cs_dispatch.h:1979
bool wait(void)
Definition: cs_dispatch.h:2051
void set_stream(int stream_id)
Definition: cs_dispatch.h:1953
void set_use_gpu(bool use_gpu)
Definition: cs_dispatch.h:1992
cs_void_context(void)
Constructor.
Definition: cs_dispatch.h:1940
cs_alloc_mode_t alloc_mode(void)
Check preferred allocation mode depending on execution policy.
Definition: cs_dispatch.h:2005
bool parallel_for_reduce(cs_lnum_t n, T &result, R &reducer, F &&f, Args &&... args)
Definition: cs_dispatch.h:2039
void set_cuda_grid(long grid_size, long block_size)
Definition: cs_dispatch.h:1961
bool use_gpu(void)
Check whether we are trying to run on GPU.
Definition: cs_dispatch.h:1998
#define cs_assert(expr)
Abort the program if the given assertion is false.
Definition: cs_assert.h:65
int cs_base_hip_get_device(void)
Return currently selected HIP devices.
Definition: cs_base_hip.cpp:816
int cs_glob_n_threads
Definition: cs_defs.cpp:168
#define restrict
Definition: cs_defs.h:148
#define CS_THR_MIN
Definition: cs_defs.h:483
static cs_lnum_t cs_align(cs_lnum_t i, cs_lnum_t m)
Given a base index i, return the next index aligned with a size m.
Definition: cs_defs.h:639
int cs_lnum_t
local mesh entity id
Definition: cs_defs.h:325
#define CS_CL_SIZE
Definition: cs_defs.h:488
void cs_dispatch_sum(T *dest, const T src, cs_dispatch_sum_type_t sum_type)
sum values using a chosen dispatch sum type.
Definition: cs_dispatch.h:2412
cs_dispatch_sum_type_t
Definition: cs_dispatch.h:95
@ CS_DISPATCH_SUM_SIMPLE
Definition: cs_dispatch.h:97
@ CS_DISPATCH_SUM_ATOMIC
Definition: cs_dispatch.h:99
#define cs_alloc_mode_device
Definition: cs_mem.h:185
cs_alloc_mode_t
Definition: cs_mem.h:46
@ CS_ALLOC_HOST
Definition: cs_mem.h:48
@ CS_ALLOC_HOST_DEVICE_SHARED
Definition: cs_mem.h:53
static void sum(const cs_mpi_wrapper &mpi_w, T &first, Vals &... values)
Sum values of a given datatype over a given communicator.
Definition: cs_parall.h:893
bool parallel_for_reduce_sum(cs_lnum_t n, T &sum, F &&f, Args &&... args)
parallel_for_reduce_sum construct using a dispatch context based on template parameter (enum) "exec_t...
Definition: cs_execution_context.h:347
bool parallel_for_i_faces(const M *m, F &&f, Args &&... args)
parallel_for_i_faces construct using a dispatch context based on template parameter (enum) "exec_type...
Definition: cs_execution_context.h:286
bool wait(void)
wait construct using a dispatch context based on template parameter of exec_type (enum)
Definition: cs_execution_context.h:543
bool parallel_for_reduce(cs_lnum_t n, T &result, R &reducer, F &&f, Args &&... args)
parallel_for_reduce construct using a dispatch context based on template parameter (enum) "exec_type"
Definition: cs_execution_context.h:442
bool parallel_for(cs_lnum_t n, F &&f, Args &&... args)
parallel_for construct using a dispatch context based on template parameter (enum) "exec_type"
Definition: cs_execution_context.h:229