C++ 临时CUDA设备阵列

C++ 临时CUDA设备阵列,c++,cuda,C++,Cuda,几个月来,我一直在玩这个盛大的CUDA实验,我发现自己做了更多的实验,并试图摆脱教程中的例子 我的问题是:如果我只想在GPU上使用数组作为临时存储,而不想将它们复制回主机进行显示/输出,那么我可以创建一个带有\uuuuuuu device\uuuuuuu双数组[numpoints]的设备数组吗那么,对于我想从GPU取回的任何东西,我需要做整个cudaMalloc,cudaMemcpy spiel,对吗?另外,一种方法和另一种方法有什么区别吗?我认为它们都在全局内存中创建数组。请参阅关于\uuu设

几个月来,我一直在玩这个盛大的CUDA实验,我发现自己做了更多的实验,并试图摆脱教程中的例子

我的问题是:如果我只想在GPU上使用数组作为临时存储,而不想将它们复制回主机进行显示/输出,那么我可以创建一个带有
\uuuuuuu device\uuuuuuu双数组[numpoints]的设备数组吗那么,对于我想从GPU取回的任何东西,我需要做整个cudaMalloc,cudaMemcpy spiel,对吗?另外,一种方法和另一种方法有什么区别吗?我认为它们都在全局内存中创建数组。

请参阅关于
\uuu设备\uuu
限定符的说明。因此,如果您声明它为
\uuuu设备\uuuu
,则无法通过
cudaMemcpy
在主机中访问它,但链接中还提到了其他内容


相反,您可以在主机代码中声明一个全局指针(即不带
\uuu设备
),并使用
cudamaloc
进行分配。因此,您可以使用
cudaMemcpy
将结果复制回主机

您可以创建、填充和使用globl内存阵列,而无需使用
cudaMemcpy
从主机复制数据进行初始化,如果这是您的要求。在下面的简单示例中,我创建了一个全局内存阵列,它直接在设备上初始化,然后在不再需要时释放它

#include<stdio.h>

__global__ void init_temp_data(float* temp_data) {
    temp_data[threadIdx.x] = 3.f;
}

__global__ void copy_global_data(float* temp_data, float* d_data) {
    d_data[threadIdx.x] = temp_data[threadIdx.x];
}

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
    if (code != cudaSuccess) 
    {
        fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
        if (abort) exit(code);
    }
}

int main() {

    float* data = (float*)malloc(16*sizeof(float));
    float* d_data; gpuErrchk(cudaMalloc((void**)&d_data,16*sizeof(float)));
    float* temp_data; gpuErrchk(cudaMalloc((void**)&temp_data,16*sizeof(float)));

    init_temp_data<<<1,16>>>(temp_data);
    gpuErrchk(cudaPeekAtLastError());
    gpuErrchk(cudaDeviceSynchronize()); 

    copy_global_data<<<1,16>>>(temp_data,d_data);
    gpuErrchk(cudaPeekAtLastError());
    gpuErrchk(cudaDeviceSynchronize()); 

    gpuErrchk(cudaFree(temp_data));
    gpuErrchk(cudaMemcpy(data,d_data,16*sizeof(float),cudaMemcpyDeviceToHost));

    for (int i=0; i<16; i++) printf("Element number %i is equal to %f\n",i,data[i]);

    getchar();

    return 0;
}
#包括
__全局无效初始临时数据(浮点*临时数据){
温度数据[threadIdx.x]=3.f;
}
__全局\无效复制\全局\数据(浮点*临时\数据,浮点*数据){
d_数据[threadIdx.x]=临时_数据[threadIdx.x];
}
#定义gpuerchk(ans){gpuAssert((ans),_文件_,_行__)}
内联void gpuAssert(cudaError\u t代码,char*文件,int行,bool abort=true)
{
如果(代码!=cudaSuccess)
{
fprintf(标准,“GPUassert:%s%s%d\n”,cudaGetErrorString(代码)、文件、行);
如果(中止)退出(代码);
}
}
int main(){
浮动*数据=(浮动*)malloc(16*sizeof(浮动));
浮动*d_数据;gpuerchk(cudamaloc((void**)和d_数据,16*sizeof(浮动));
浮点*临时数据;gpuerchk(cudaMalloc((void**)和临时数据,16*sizeof(浮点));
初始温度数据(温度数据);
gpuerchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
复制全局数据(临时数据、数据);
gpuerchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
gpuErrchk(cudaFree(临时数据));
gpuErrchk(cudaMemcpy(数据,数据,16*sizeof(float),cudaMemcpyDeviceToHost));

对于(int i=0;icudamempy可用于复制到静态声明的
\uuuu设备\uuuu
内存。这就是
cudaGetSymbolAddress
cudaGetSymbolSize
的目的——您可以在运行时获得静态符号的详细信息,然后像使用任何其他主机地址一样使用它们。@talonmies:很高兴知道这一点。刚刚尝试过,它就可以工作了。)nk你。如果你能回答同样的问题,我会投赞成票(看起来这就是问题海报所要找的)。