单独模板函数中的cudaMalloc和cudaMemcpy问题

问题描述

我正在研究仅计算正方形和立方体的基本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,size_t SIZE_BYTE)
{
    AllocateMem(device_arr,SIZE_BYTE);
    if (cudaMemcpy(device_arr,cudaMemcpyHostToDevice) != cudaSuccess) // return 1 which is equal to cudaErrorInvalidValue
    {
        throw std::bad_alloc();
    }
}

当我按以下方式编写此函数时,它可以完美运行;

template <typename T>
void CopyMemToDevice(const T* host_arr,size_t SIZE_BYTE)
{
    cudaMalloc(&device_arr,SIZE_BYTE);  
    if (cudaMemcpy(device_arr,cudaMemcpyHostToDevice) != cudaSuccess)
    {
        throw std::bad_alloc();
    }
}

此外,我知道AllocateMem函数有效,cudaMalloc返回0,即cudaSuccess

我的问题是,在相同函数和不同函数中调用cudaMalloccudaMemcpy有什么区别?当我调用分隔的函数时,为什么会出现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

解决方法

如评论中的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);

有效。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...