Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CudaUtils.hpp 4.69 KiB
#ifndef AIDGE_BACKEND_CUDA_CUDA_UTILS_H
#define AIDGE_BACKEND_CUDA_CUDA_UTILS_H

#include <string>
#include <memory>
#include <sstream>
#include <iostream>
#include <stdexcept>

#include <cublas_v2.h>
#include <cuda.h>
#include <cudnn.h>

#include "aidge/data/half.hpp"
#include "aidge/utils/ErrorHandling.hpp"

#define CHECK_CUDNN_STATUS(status)                                             \
    do {                                                                       \
        const cudnnStatus_t e = (status);                                      \
        if (e != CUDNN_STATUS_SUCCESS) {                                       \
            std::stringstream error;                                           \
            error << "CUDNN failure: " << cudnnGetErrorString(e) << " ("       \
                  << static_cast<int>(e) << ") in " << __FILE__ << ':' << __LINE__;         \
            int status_dev;                                                           \
            if (cudaGetDevice(&status_dev) == cudaSuccess)                            \
                error << " on device #" << status_dev;                                \
            std::cerr << error.str() << std::endl;                             \
            cudaDeviceReset();                                                 \
            throw std::runtime_error(error.str());                             \
        }                                                                      \
    } while(0)

#define CHECK_CUDA_STATUS(status)                                              \
    do {                                                                       \
        const cudaError_t e = (status);                                        \
        if ((e) != cudaSuccess) {                                              \
            std::stringstream error;                                           \
            error << "Cuda failure: " << cudaGetErrorString(e) << " ("         \
                  << static_cast<int>(e) << ") in " << __FILE__ << ':' << __LINE__;         \
            int status_dev;                                                           \
            if (cudaGetDevice(&status_dev) == cudaSuccess)                            \
                error << " on device #" << status_dev;                                \
            std::cerr << error.str() << std::endl;                             \
            cudaDeviceReset();                                                 \
            throw std::runtime_error(error.str());                             \
        }                                                                      \
    } while(0)

#define CHECK_CUBLAS_STATUS(status)                                            \
    do {                                                                       \
        const cublasStatus_t e = (status);                                     \
        if (e != CUBLAS_STATUS_SUCCESS) {                                      \
            std::stringstream error;                                           \
            error << "Cublas failure: "                                        \
                  << Aidge::Cuda::cublasGetErrorString(e) << " ("               \
                  << static_cast<int>(e) << ") in " << __FILE__ << ':' << __LINE__;         \
            int status_dev;                                                           \
            if (cudaGetDevice(&status_dev) == cudaSuccess)                            \
                error << " on device #" << status_dev;                                \
            std::cerr << error.str() << std::endl;                             \
            cudaDeviceReset();                                                 \
            throw std::runtime_error(error.str());                             \
        }                                                                      \
    } while(0)

namespace Aidge {
namespace Cuda {
    // CuDNN scaling parameters are typically "alpha" and "beta".
    // Their type must be "float" for HALF and FLOAT (default template)
    // and "double" for DOUBLE (specialized template)
    template <class T>
    struct cudnn_scaling_type {
        typedef float type;
    };

    template <>
    struct cudnn_scaling_type<double> {
        typedef double type;
    };

    template <class T>
    struct cuda_type {
        typedef T type;
    };

    template <>
    struct cuda_type<half_float::half> {
        typedef __half type;
    };

    const char* cublasGetErrorString(cublasStatus_t error);

    // Enable Peer-to-Peer communications between devices
    // when it is possible
    void setMultiDevicePeerAccess(unsigned int size, unsigned int* devices);
}
}

#endif // AIDGE_BACKEND_CUDA_CUDA_UTILS_H