CUDA全局(如C中)分配给设备内存的动态数组

CUDA全局(如C中)分配给设备内存的动态数组,cuda,nvidia,Cuda,Nvidia,所以,我试图写一些代码,利用Nvidia的CUDA架构。我注意到,在设备之间进行复制确实会损害我的整体性能,因此现在我正试图将大量数据移动到设备上 由于这些数据用于许多函数,我希望它是全局的。是的,我可以传递指针,但我真的很想知道在这个例子中如何使用全局变量 因此,我有一些设备函数想要访问设备分配的数组 理想情况下,我可以这样做: __device__ float* global_data; main() { cudaMalloc(global_data); kernel1<&l

所以,我试图写一些代码,利用Nvidia的CUDA架构。我注意到,在设备之间进行复制确实会损害我的整体性能,因此现在我正试图将大量数据移动到设备上

由于这些数据用于许多函数,我希望它是全局的。是的,我可以传递指针,但我真的很想知道在这个例子中如何使用全局变量

因此,我有一些设备函数想要访问设备分配的数组

理想情况下,我可以这样做:

__device__ float* global_data;

main()
{
  cudaMalloc(global_data);
  kernel1<<<blah>>>(blah); //access global data
  kernel2<<<blah>>>(blah); //access global data again
}

虽然这不需要cudamaloc调用,但我更喜欢动态分配方法。

花些时间关注NVIDIA提供的丰富文档

从编程指南:

float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));
这是如何分配内存的一个简单示例。现在,在内核中,您应该接受指向浮点的指针,如下所示:

__global__
void kernel1(float *some_neat_data)
{
    some_neat_data[threadIdx.x]++;
}

__global__
void kernel2(float *potentially_that_same_neat_data)
{
    potentially_that_same_neat_data[threadIdx.x] *= 0.3f;
}
现在您可以这样调用它们:

float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));

kernel1<<<1,128>>>(devPtr);
kernel2<<<1,128>>>(devPtr);
float*devPtr;
Cudamaloc((void**)和devPtr,256*sizeof(*devPtr));
cudaMemset(devPtr,0,256*sizeof(*devPtr));
内核1(devPtr);
内核2(devPtr);
因为这些数据被用于许多领域 功能,我希望它是 全球

使用globals没有什么好的理由。这绝对不是一个。我将把它作为一个练习来扩展这个示例,以包括将“devPtr”移动到全局范围

编辑:

好的,最基本的问题是:内核只能访问设备内存,它们只能使用GPU的全局作用域指针。当从CPU调用内核时,幕后发生的是指针和原语在内核执行之前被复制到GPU寄存器和/或共享内存中

因此,我最接近的建议是:使用cudaMemcpyToSymbol()实现您的目标。但是,在背景下,考虑不同的方法可能是正确的。
#include <algorithm>

__constant__ float devPtr[1024];

__global__
void kernel1(float *some_neat_data)
{
    some_neat_data[threadIdx.x] = devPtr[0] * devPtr[1];
}

__global__
void kernel2(float *potentially_that_same_neat_data)
{
    potentially_that_same_neat_data[threadIdx.x] *= devPtr[2];
}


int main(int argc, char *argv[])
{
    float some_data[256];
    for (int i = 0; i < sizeof(some_data) / sizeof(some_data[0]); i++)
    {
        some_data[i] = i * 2;
    }
    cudaMemcpyToSymbol(devPtr, some_data, std::min(sizeof(some_data), sizeof(devPtr) ));
    float* otherDevPtr;
    cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
    cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));

    kernel1<<<1,128>>>(otherDevPtr);
    kernel2<<<1,128>>>(otherDevPtr);

    return 0;
}
#包括
__常量浮点数devPtr[1024];
__全球的__
void kernel1(浮动*一些整洁的数据)
{
一些整洁的数据[threadIdx.x]=devPtr[0]*devPtr[1];
}
__全球的__
void kernel2(浮动*可能是相同的数据)
{
可能是相同的整洁数据[threadIdx.x]*=devPtr[2];
}
int main(int argc,char*argv[])
{
浮动一些_数据[256];
对于(int i=0;i

在本例中,不要忘记“--host compilation=c++”。

Erm,将devPtr移动到全局范围的问题正是我的问题

我有一个实现就是这样做的,两个内核有一个指向传入数据的指针。我明确地不想传递那些指针


我已经相当仔细地阅读了文档,并在英伟达论坛上找到了(谷歌搜索了一个小时左右),但是我还没有找到一个实际运行的全局动态设备数组的实现(我尝试了几个编译,然后以新的有趣的方式失败)。

#include <algorithm>

#define NDEBUG
#define CUT_CHECK_ERROR(errorMessage) do {                                 \
        cudaThreadSynchronize();                                           \
         cudaError_t err = cudaGetLastError();                             \
         if( cudaSuccess != err) {                                         \
                     fprintf(stderr, "Cuda error: %s in file '%s' in line %i : %s.\n",    \
                                             errorMessage, __FILE__, __LINE__, cudaGetErrorString( err) );\
                     exit(EXIT_FAILURE);                                                  \
                 } } while (0)


__device__ float *devPtr;

__global__
void kernel1(float *some_neat_data)
{
    devPtr = some_neat_data;
}

__global__
void kernel2(void)
{
    devPtr[threadIdx.x] *= .3f;
}


int main(int argc, char *argv[])
{
    float* otherDevPtr;
    cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
    cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));

    kernel1<<<1,128>>>(otherDevPtr);
    CUT_CHECK_ERROR("kernel1");

    kernel2<<<1,128>>>();

    CUT_CHECK_ERROR("kernel2");

    return 0;
}
#包括
#定义NDEBUG
#定义剪切检查错误(errorMessage)do{\
cudaThreadSynchronize()\
cudaError_t err=cudaGetLastError()\
如果(cudaSuccess!=err){\
fprintf(stderr,“Cuda错误:%s,位于文件“%s”的第%i:%s行。\n”\
错误消息、文件、行、cudaGetErrorString(err))\
退出(退出失败)\
}}while(0)
__设备浮点数*devPtr;
__全球的__
void kernel1(浮动*一些整洁的数据)
{
devPtr=一些整洁的数据;
}
__全球的__
void内核2(void)
{
devPtr[threadIdx.x]*=.3f;
}
int main(int argc,char*argv[])
{
浮动*其他devptr;
Cudamaloc((void**)和其他devptr,256*sizeof(*其他devptr));
cudaMemset(otherDevPtr,0,256*sizeof(*otherDevPtr));
内核1(其他devptr);
剪切检查错误(“内核1”);
内核2();
剪切检查错误(“内核2”);
返回0;
}

试一试。

查看SDK附带的示例。许多示例项目都是通过示例学习的好方法。

我尝试了分配临时指针并将其传递给类似于kernel1的简单全局函数的解决方案

好消息是它确实有效:)

但是,我认为这会混淆编译器,因为我现在在尝试访问全局数据时会得到“Advisory:无法判断指针指向什么,假设全局内存空间”。幸运的是,这个假设恰好是正确的,但是警告很烦人

无论如何,我已经看过很多例子,并且通过英伟达练习,重点是让输出说“正确”。然而,我并没有全部看过。如果有人知道一个sdk示例,他们在其中执行动态全局设备内存分配,我仍然想知道

由于这些数据用于许多函数,我希望它是全局的

-

使用globals没有什么好的理由。这绝对不是一个。我将把它作为一个例子 练习扩展此示例,以包括将“devPtr”移动到全局范围


如果内核在一个由数组组成的大型常量结构上运行会怎么样?使用所谓的常量内存不是一个选项,因为它的大小非常有限。。所以你必须把它放在全局内存中。

是的,这是我最初的解决方案。在…上
#include <algorithm>

#define NDEBUG
#define CUT_CHECK_ERROR(errorMessage) do {                                 \
        cudaThreadSynchronize();                                           \
         cudaError_t err = cudaGetLastError();                             \
         if( cudaSuccess != err) {                                         \
                     fprintf(stderr, "Cuda error: %s in file '%s' in line %i : %s.\n",    \
                                             errorMessage, __FILE__, __LINE__, cudaGetErrorString( err) );\
                     exit(EXIT_FAILURE);                                                  \
                 } } while (0)


__device__ float *devPtr;

__global__
void kernel1(float *some_neat_data)
{
    devPtr = some_neat_data;
}

__global__
void kernel2(void)
{
    devPtr[threadIdx.x] *= .3f;
}


int main(int argc, char *argv[])
{
    float* otherDevPtr;
    cudaMalloc((void**)&otherDevPtr, 256 * sizeof(*otherDevPtr));
    cudaMemset(otherDevPtr, 0, 256 * sizeof(*otherDevPtr));

    kernel1<<<1,128>>>(otherDevPtr);
    CUT_CHECK_ERROR("kernel1");

    kernel2<<<1,128>>>();

    CUT_CHECK_ERROR("kernel2");

    return 0;
}