STIR 6.5.0
cuda_utilities.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2024, 2026, University College London
3 Copyright (C) 2025, University of Milano-Bicocca
4 This file is part of STIR.
5
6 SPDX-License-Identifier: Apache-2.0
7
8 See STIR/LICENSE.txt for details
9*/
10
11#ifndef __stir_cuda_utilities_H__
12#define __stir_cuda_utilities_H__
13
22#include "stir/Array.h"
23#include "stir/info.h"
24#include "stir/error.h"
25#ifdef __CUDACC__
26# include <cuda_runtime.h>
27#else
28# ifndef CUVEC_DISABLE_CUDA
29# define CUVEC_DISABLE_CUDA
30# endif
31#endif
32#include "cuvec.cuh"
33#include <vector>
34#include <memory>
35
36START_NAMESPACE_STIR
37
38#ifndef __CUDACC__
39# ifndef __host__
40# define __host__
41# endif
42# ifndef __device__
43# define __device__
44# endif
45#endif
46
47#ifndef __CUDACC__
48struct cuda_dim3
49{
50 unsigned int x = 1, y = 1, z = 1;
51};
52struct cuda_int3
53{
54 int x = 0, y = 0, z = 0;
55};
56#else
57typedef dim3 cuda_dim3;
58typedef int3 cuda_int3;
59#endif
60
62
65template <int num_dimensions, typename elemT>
66void array_to_device(elemT* dev_data, const Array<num_dimensions, elemT>& stir_array);
67
69
72template <int num_dimensions, typename elemT>
73void array_to_device(CuVec<elemT>& dev_data, const Array<num_dimensions, elemT>& stir_array);
74
76
80template <int num_dimensions, typename elemT>
81void array_to_host(Array<num_dimensions, elemT>& stir_array, const elemT* dev_data, bool /* sync */ = true);
83
87template <int num_dimensions, typename elemT>
88void array_to_host(Array<num_dimensions, elemT>& stir_array, const CuVec<elemT>& dev_data, bool sync = true);
89
90#ifdef __CUDACC__
91
93template <typename elemT>
94__device__ inline void
95blockReduction(elemT* shared_mem, int thread_in_block, int block_threads)
96{
97 for (int stride = block_threads / 2; stride > 0; stride /= 2)
98 {
99 if (thread_in_block < stride)
100 shared_mem[thread_in_block] += shared_mem[thread_in_block + stride];
101 __syncthreads();
102 }
103}
104
106template <typename elemT>
107__device__ inline double
108atomicAddGeneric(double* address, elemT val)
109{
110# if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 600
111 return atomicAdd(address, static_cast<double>(val));
112# else
113 if (threadIdx.x == 0 && threadIdx.y == 0 && threadIdx.z == 0 && blockIdx.x == 0 && blockIdx.y == 0 && blockIdx.z == 0)
114 {
115 printf("CudaGibbsPenalty: atomicAdd(double) unsupported on this GPU. "
116 "Upgrade to compute capability >= 6.0 or check code at "
117 "sources/STIR/src/include/stir/cuda_utilities.h:108.\n");
118 asm volatile("trap;");
119 }
120 return 0.0; // never reached
121 // Emulate atomicAdd for double precision on pre-Pascal architectures
122 // unsigned long long int* address_as_ull = reinterpret_cast<unsigned long long int*>(address);
123 // unsigned long long int old = *address_as_ull, assumed;
124
125 // do
126 // {
127 // assumed = old;
128 // double updated = __longlong_as_double(assumed) + dval;
129 // old = atomicCAS(address_as_ull, assumed, __double_as_longlong(updated));
130 // } while (assumed != old);
131
132 // return __longlong_as_double(old);
133# endif
134}
135
137inline void
138checkCudaError(const std::string& operation)
139{
140 cudaError_t cuda_error = cudaGetLastError();
141 if (cuda_error != cudaSuccess)
142 {
143 const char* err = cudaGetErrorString(cuda_error);
144 error(std::string("CudaGibbsPrior: CUDA error in ") + operation + ": " + err);
145 }
146}
147#endif
148
149END_NAMESPACE_STIR
150#endif
defines the stir::Array class for multi-dimensional (numeric) arrays
This class defines multi-dimensional (numeric) arrays.
Definition Array.h:78
Declaration of stir::error().
void array_to_host(Array< num_dimensions, elemT > &stir_array, const elemT *dev_data, bool=true)
copy CUDA pointer to Array
void array_to_device(elemT *dev_data, const Array< num_dimensions, elemT > &stir_array)
copy an Array to pre-allocated device memory
Declaration of stir::info().