【问题标题】:Problem with cudaMalloc and cudaMemcpy in seperate template function [duplicate]单独模板函数中 cudaMalloc 和 cudaMemcpy 的问题[重复]
【发布时间】:2020-12-25 21:55:04
【问题描述】:

我正在开发只计算平方和立方的基本 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

我的问题是在同一个函数和不同函数中调用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

【问题讨论】:

  • 您通过值将pgpu_input 传递给AllocateMem。调用者看不到函数内对该参数所做的更改。在main 中,pgpu_input 仍然是nullptr
  • 啊,真是个愚蠢的错误。谢谢,现在可以了。

标签: c++ templates cuda


【解决方案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);

有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 2016-06-03
    • 2016-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多