10#ifndef FZ_ANS_DIETGPU_UTILS_DEVICEUTILS_H
11#define FZ_ANS_DIETGPU_UTILS_DEVICEUTILS_H
16#include <cuda_runtime.h>
20#include <unordered_map>
22#define CUDA_VERIFY(X) \
25 if (err__ != cudaSuccess) { \
26 std::cout << "CUDA error " << fz::ans::errorToName(err__) \
27 << " " << fz::ans::errorToString(err__) \
33#define CUDA_TEST_ERROR() \
35 CUDA_VERIFY(cudaDeviceSynchronize()); \
38#define CUDA_TEST_ERROR() \
40 CUDA_VERIFY(cudaGetLastError()); \
44namespace fz {
namespace ans {
46constexpr int kWarpSize = 32;
48inline std::string errorToString(cudaError_t err) {
49 return std::string(cudaGetErrorString(err));
52inline std::string errorToName(cudaError_t err) {
53 return std::string(cudaGetErrorName(err));
56inline int getCurrentDevice() {
58 CUDA_VERIFY(cudaGetDevice(&dev));
62inline void setCurrentDevice(
int device) {
63 CUDA_VERIFY(cudaSetDevice(device));
66inline int getNumDevices() {
68 cudaError_t err = cudaGetDeviceCount(&numDev);
69 if (cudaErrorNoDevice == err) {
77inline void synchronizeAllDevices() {
78 for (
int i = 0; i < getNumDevices(); ++i) {
79 CUDA_VERIFY(cudaSetDevice(i));
80 CUDA_VERIFY(cudaDeviceSynchronize());
84inline const cudaDeviceProp& getDeviceProperties(
int device) {
85 static std::mutex mutex;
86 static std::unordered_map<int, cudaDeviceProp> properties;
88 std::lock_guard<std::mutex> guard(mutex);
90 auto it = properties.find(device);
91 if (it == properties.end()) {
93 CUDA_VERIFY(cudaGetDeviceProperties(&prop, device));
94 properties[device] = prop;
95 it = properties.find(device);
100inline const cudaDeviceProp& getCurrentDeviceProperties() {
101 return getDeviceProperties(getCurrentDevice());
104inline int getMaxThreads(
int device) {
105 return getDeviceProperties(device).maxThreadsPerBlock;
108inline int getMaxThreadsCurrentDevice() {
109 return getMaxThreads(getCurrentDevice());
112inline size_t getMaxSharedMemPerBlock(
int device) {
113 return getDeviceProperties(device).sharedMemPerBlock;
116inline size_t getMaxSharedMemPerBlockCurrentDevice() {
117 return getMaxSharedMemPerBlock(getCurrentDevice());
120inline int getDeviceForAddress(
const void* p) {
124 cudaPointerAttributes att;
125 cudaError_t err = cudaPointerGetAttributes(&att, p);
126 if (err == cudaErrorInvalidValue) {
127 err = cudaGetLastError();
130#if CUDA_VERSION < 10000
131 if (att.memoryType == cudaMemoryTypeHost) {
137 if (att.type == cudaMemoryTypeDevice) {
145inline bool getFullUnifiedMemSupport(
int device) {
146 const auto& prop = getDeviceProperties(device);
147 return (prop.major >= 6);
150inline bool getFullUnifiedMemSupportCurrentDevice() {
151 return getFullUnifiedMemSupport(getCurrentDevice());
156 explicit DeviceScope(
int device) {
158 int curDevice = getCurrentDevice();
159 if (curDevice != device) {
160 prevDevice_ = curDevice;
161 setCurrentDevice(device);
168 if (prevDevice_ != -1) {
169 setCurrentDevice(prevDevice_);
178 explicit CudaEvent(cudaStream_t stream,
bool timer =
false) : event_(nullptr) {
179 CUDA_VERIFY(cudaEventCreateWithFlags(
180 &event_, timer ? cudaEventDefault : cudaEventDisableTiming));
181 CUDA_VERIFY(cudaEventRecord(event_, stream));
183 CudaEvent(
const CudaEvent&) =
delete;
184 CudaEvent(CudaEvent&& event) noexcept : event_(event.event_) {
185 event.event_ =
nullptr;
188 if (event_) CUDA_VERIFY(cudaEventDestroy(event_));
190 CudaEvent& operator=(CudaEvent&& event)
noexcept {
191 event_ =
event.event_;
192 event.event_ =
nullptr;
195 CudaEvent& operator=(CudaEvent&) =
delete;
196 inline cudaEvent_t get() {
return event_; }
197 void streamWaitOnEvent(cudaStream_t stream) {
198 CUDA_VERIFY(cudaStreamWaitEvent(stream, event_, 0));
200 void cpuWaitOnEvent() { CUDA_VERIFY(cudaEventSynchronize(event_)); }
201 float timeFrom(CudaEvent& from) {
204 CUDA_VERIFY(cudaEventElapsedTime(&ms, from.event_, event_));
213 explicit CudaStream(
int flags = cudaStreamDefault) : stream_(nullptr) {
214 CUDA_VERIFY(cudaStreamCreateWithFlags(&stream_, flags));
216 CudaStream(
const CudaStream&) =
delete;
217 CudaStream(CudaStream&& stream) noexcept : stream_(stream.stream_) {
218 stream.stream_ =
nullptr;
221 if (stream_) CUDA_VERIFY(cudaStreamDestroy(stream_));
223 CudaStream& operator=(CudaStream&& stream)
noexcept {
224 stream_ = stream.stream_;
225 stream.stream_ =
nullptr;
228 CudaStream& operator=(CudaStream&) =
delete;
229 inline cudaStream_t get() {
return stream_; }
230 operator cudaStream_t() {
return stream_; }
231 static CudaStream make() {
return CudaStream(); }
232 static CudaStream makeNonBlocking() {
return CudaStream(cudaStreamNonBlocking); }
234 cudaStream_t stream_;