我正在研究仅计算正方形和立方体的基本CUDA程序。但是我不想用main
编写所有代码,因此我将其中的一些功能分为模板。创建模板功能没有特殊目的。只有,我想尝试一下。问题与是否将函数调用为cudaMalloc
之类的裸函数有关。如果我使用函数调用,它将失败。让我展示一下;
kernel.cuh
#ifndef KERNEL_CUH_
#define KERNEL_CUH_
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <exception>
#include <iostream>
struct GPUVars
{
private:
size_t block_sz;
size_t thread_sz;
public:
GPUVars(size_t block, size_t thread) : block_sz{ block }, thread_sz{ thread } {};
size_t GetBlockSize()const { return block_sz; };
size_t GetThreadSize()const { return thread_sz; }
};
inline bool check_device()
{
auto cuda_device_count{ 0 };
cudaGetDeviceCount(&cuda_device_count);
return cuda_device_count > 0;
}
template <typename T>
void AllocateMem(T* arr, size_t SIZE_BYTE)
{
if (cudaMalloc(&arr, SIZE_BYTE) != cudaSuccess)
{
throw std::bad_alloc();
}
}
template <typename T>
void CopyMemToDevice(const T* host_arr, T* device_arr, size_t SIZE_BYTE)
{
if (cudaMemcpy(device_arr, host_arr, SIZE_BYTE, cudaMemcpyHostToDevice) != cudaSuccess)
{
throw std::bad_alloc();
}
}
#endif
main.cpp
#include <iostream>
#include <random>
#include <iomanip>
#include <cassert>
#include "timer.h"
#include "cpu_calc.h"
#include "kernel.cuh"
template <typename T>
void RandNumberGen(T lower, T upper, T* arr, size_t SIZE_ARR)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(lower, upper);
for (size_t i = 0; i < SIZE_ARR; ++i)
{
arr[i] = dis(gen);
}
}
int main()
{
assert(check_device() == true);
constexpr size_t SIZE_ARR{ 1024 };
double input_arr[SIZE_ARR]{ 0 };
RandNumberGen(1.0, 10000.0, input_arr, SIZE_ARR);
constexpr size_t SIZE_BYTE = SIZE_ARR * sizeof(double);
std::cout << std::setprecision(9) << std::fixed;
double cpu_output[SIZE_ARR]{ 0 };
// SQUARE
auto time = CPUTimer(&cpu_output[0], &input_arr[0], SIZE_ARR, &CPUSquare);
std::cout << "CPU square opeartion with " << SIZE_ARR << " size array takes " << std::setw(18) << time << " ns\n";
GPUVars gpu_vars{ 0, 1024 };
double* pgpu_input = nullptr;
double gpu_output[SIZE_ARR];
double* pgpu_output = nullptr;
AllocateMem(pgpu_input, SIZE_BYTE);
AllocateMem(pgpu_output, SIZE_BYTE);
CopyMemToDevice(input_arr, pgpu_input, SIZE_BYTE);
}
当我调用CopyMemToDevice
函数时,由于cudaMemCpy
函数返回等于cudaErrorInvalidValue
的函数而引发错误。
此外,如果我将CopyMemToDevice
函数更改为与此相同;
template <typename T>
void CopyMemToDevice(const T* host_arr, T* device_arr, size_t SIZE_BYTE)
{
AllocateMem(device_arr, SIZE_BYTE);
if (cudaMemcpy(device_arr, host_arr, SIZE_BYTE, cudaMemcpyHostToDevice) != cudaSuccess) // return 1 which is equal to cudaErrorInvalidValue
{
throw std::bad_alloc();
}
}
当我按以下方式编写此函数时,它可以完美运行;
template <typename T>
void CopyMemToDevice(const T* host_arr, T* device_arr, size_t SIZE_BYTE)
{
cudaMalloc(&device_arr, SIZE_BYTE);
if (cudaMemcpy(device_arr, host_arr, SIZE_BYTE, cudaMemcpyHostToDevice) != cudaSuccess)
{
throw std::bad_alloc();
}
}
此外,我知道AllocateMem
函数有效,cudaMalloc
返回0,即cudaSuccess
。
我的问题是,在相同函数和不同函数中调用cudaMalloc
和cudaMemcpy
有什么区别?当我调用分隔的函数时,为什么会出现cudaErrorInvalidValue : This indicates that one or more of the parameters passed to the API call is not within an acceptable range of values.
错误?预先感谢。
我正在使用Visual Studio 2019 16.7.1和CUDA 10.1
答案 0 :(得分:1)
如评论中的Igor Tandetnik
所述。该问题仅与pass by value
有关。我像这样更新了AllocateMem
函数;
template <typename T>
void AllocateMem(T** arr, size_t SIZE_BYTE)
{
if (cudaMalloc(arr, SIZE_BYTE); != cudaSuccess)
{
throw std::bad_alloc();
}
}
这样打电话,
AllocateMem(&pgpu_output, SIZE_BYTE);
有效。