-2

我想将每个线程使用的一组初始化值复制到__global__内存中。我已将它们总结为一个结构。__global__但是,将其放入内存存在多个问题。首先,VS2015 告诉我__constant__这一行的“变量不支持动态初始化”: __constant__ initValsStruct d_initVals;

其次,它告诉我“在这一行中 没有合适的转换函数 from initValsStructto :const void *cudaMemcpyToSymbol(d_initVals, &h_initVals, sizeof(initValsStruct));

这可能是一个非常基本的 C 或 CUDA 问题,但是将单个结构复制到__global__内存的最佳方法是什么?

我尝试了代码中的内容;我在 CUDA 开发论坛的某个地方找到了一个示例,其中一些__constant__内存(int1024 个元素的数组)以相同的方式初始化。

typedef struct
{
    unsigned int voxels_x = 0;
    unsigned int voxels_y = 0;
    unsigned int voxels_z;

    //Input and output data amounts
    unsigned int n_lines;
    unsigned int TD_samples;

    //amount of total calculations
    unsigned int n_calc;
} initValsStruct;

initValsStruct h_initVals; //host struct to be copied into __global__ memory
__constant__ initValsStruct d_initVals; //where it has to be copied to

int main(){
    //here I initialize every element of the initValsStruct h_initVals, so it is initialized

    cudaMemcpyToSymbol(d_initVals, &h_initVals, sizeof(initValsStruct));
}

这是我访问它的方式:

typedef struct
{
    int device = 0;
    double  *d_xre, *d_xim, //input device arrays
            *d_yre, *d_yim, //output device arrays
            *h_xre_pl, *h_xim_pl, //page locked input host arrays
            *h_yre_pl, *h_yim_pl; //page locked output host arrays
} IOdataPtr;

__device__ void computation(int currentComputation, IOdataPtr ptr) //actual computation kernel
{
    int index;

    for (int i = 0; i < d_initVals.n_lines * PARAMETERS_PER_LINE; i++) {
        index = currentComputation * d_initVals.n_lines * PARAMETERS_PER_LINE + i;
        ptr.d_yre[index] = ptr.d_xre[index];
        ptr.d_yim[index] = ptr.d_xim[index];
    }
}

我希望它能够以与将 initVals 结构作为参数提供给内核时相同的方式进行编译和运行

4

1 回答 1

-1

阅读您的代码,我不清楚您要做什么。但是您的问题是“我想将每个线程使用的一组初始化值复制到全局内存中”,因此我将选择以非常直接的方式回答该问题。数据通过主机从主机复制到设备cudaMemcpy功能。下面是一个成功的例子。

结构:

typedef struct
{
    unsigned int voxels_x;
    unsigned int voxels_y;
    unsigned int voxels_z;

    // Input and output data amounts
    unsigned int n_lines;
    unsigned int TD_samples;

    // amount of total calculations
    unsigned int n_calc;
} initValsStruct;

在主机上初始化它并将其复制到设备cudaMemcpy

int main(void) {
    initValsStruct h_params;
    initValsStruct *d_params;
    h_params.n_calc = 10;
    // etc. initialization

    // Copy struct to device
    cudaMemcpy(d_params, &h_params, sizeof(initValsStruct), cudaMemcpyHostToDevice);

    // Struct d_params now has whatever values were in h_params. 
    // Unlike this example, be sure to use proper error-checking 
    // for all CUDA API calls

    // some kernel calls

    // done
    return 0;
}

您也可以使用cudaMallocManaged,它既方便又干净一些。我强烈推荐它。

您的内核调用应该initValsStruct在其函数签名中使用指针。

__device__ void computation(int currentComputation, initValsStruct *ptr, IOdataPtr *ptr) //actual computation kernel
{
    // do something
}

这会将您的结构放入全局内存中,任何接收到它的指针的设备函数都可以在其中使用它。您的代码似乎正在尝试使用__constant__关键字,这表明您正在尝试使用设备端常量缓存。我建议先尝试使用全局内存,了解如何使用 CUDA API 的基本功能,然后再深入研究如何使用常量缓存。你的结构有一些默认值(例如动态初始化),这是被禁止的;像我上面所做的那样,在没有任何动态初始化的情况下重新定义您的结构,然后首先在主机上初始化结构,然后使用cudaMemcpyToSymbol.

于 2019-08-13T01:21:12.427 回答