关于nvidia:CUDA全局(分配给C)动态数组分配给设备内存

关于nvidia:CUDA全局(分配给C)动态数组分配给设备内存

CUDA global (as in C) dynamic arrays allocated to device memory

因此,我试图编写一些利用Nvidia的CUDA架构的代码。我注意到往返于设备的复制确实损害了我的整体性能,所以现在我正尝试将大量数据移至设备上。

由于此数据用于多种功能,我希望它具有全局性。是的,我可以传递指针,但是我真的很想知道在这种情况下如何使用全局变量。

因此,我具有要访问设备分配的阵列的设备功能。

理想情况下,我可以执行以下操作:

1
2
3
4
5
6
7
8
__device__ float* global_data;

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

但是,我还没有弄清楚如何创建一个动态数组。我通过声明数组来找出解决方法,如下所示:

1
__device__ float global_data[REALLY_LARGE_NUMBER];

尽管不需要cudaMalloc调用,但我更喜欢动态分配方法。


类似的事情可能应该起作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include

#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.\
",    \\
                                             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;
}

旋转一下。


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

好消息是它确实起作用:)

但是,当我尝试访问全局数据时,由于我现在得到"建议:假设全局内存空间,无法告诉指针指向什么",我认为它会使编译器感到困惑。幸运的是,这个假设恰好是正确的,但是警告很烦人。

无论如何,为了记录-我查看了许多示例,并进行了nvidia练习,其中的重点是使输出说"正确!"。但是,我还没有全部查看。如果有人知道他们在其中进行动态全局设备内存分配的sdk示例,我仍然想知道。


花一些时间专注于NVIDIA提供的丰富文档。

摘自《编程指南》:

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

这是如何分配内存的简单示例。现在,在您的内核中,您应该接受一个指向浮点数的指针,如下所示:

1
2
3
4
5
6
7
8
9
10
11
__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;
}

所以现在您可以像这样调用它们:

1
2
3
4
5
6
float* devPtr;
cudaMalloc((void**)&devPtr, 256 * sizeof(*devPtr));
cudaMemset(devPtr, 0, 256 * sizeof(*devPtr));

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

As this data is used in numerous
functions, I would like it to be
global.

使用全局变量的理由很少。这绝对不是一个。我将把它作为扩展此示例的练习,以包括将" devPtr"移动到全局范围。

编辑:

好吧,根本的问题是这样的:您的内核只能访问设备内存,并且它们只能使用的全局范围指针是GPU的。从CPU调用内核时,在后台发生的情况是,在内核执行之前,指针和基元被复制到GPU寄存器和/或共享内存中。

因此,我能建议的最接近的是:使用cudaMemcpyToSymbol()来实现您的目标。但是,在后台,请考虑另一种方法可能是正确的事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include

__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;
}

在此示例中,请不要忘记'--host-compilation = c'。


As this data is used in numerous functions, I would like it to be global.

-

There are few good reasons to use globals. This definitely is not one. I'll leave it as an
exercise to expand this example to include moving"devPtr" to a global scope.

如果内核在由数组组成的大型const结构上运行,该怎么办?不能使用所谓的常量内存,因为它的大小非常有限。因此,您必须将其放入全局内存中。


签出SDK随附的示例。这些示例项目中的许多都是通过示例进行学习的一种不错的方法。


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

我有一个实现该功能的实现,两个内核都有一个指向数据的指针。我明确地不想传入这些指针。

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


推荐阅读

    linux操作数据库命令?

    linux操作数据库命令?,地址,服务,系统,密码,数据库,工具,名字,首页,命令,参

    linux下载数据命令?

    linux下载数据命令?,软件,工具,数据,系统,代理,官网,网络,名称,网址,盘中,在l

    linux清理内存命令行?

    linux清理内存命令行?,策略,数据,系统,名称,不了,管理,情况,工作,一致,时间,l

    linux测试性能命令?

    linux测试性能命令?,系统,网络,信息,工具,状态,地址,指标,情况,分析,下行,五

    做数据linux常用命令?

    做数据linux常用命令?,工作,系统,基础,网络,数据,标准,管理,工具,地址,命令,l

    linux分析内存命令?

    linux分析内存命令?,情况,系统,信息,分析,命令,地址,内存,工具,下来,数据,lin

    linux查重复数据命令?

    linux查重复数据命令?,工具,数据,系统,电脑,名字,资料,代码,百度,标准,技术,

    linux的内存查看命令?

    linux的内存查看命令?,系统,情况,信息,数据,工具,命令,内存,第一,环境,电脑,

    linux数据库升级命令?

    linux数据库升级命令?,系统,信息,时间,最新,网络,名字,地址,管理,简介,传播,l

    linux命令行查内存?

    linux命令行查内存?,系统,情况,信息,状态,工具,内存,电脑,分析,数据,命令,怎

    linux看剩余内存命令?

    linux看剩余内存命令?,系统,情况,工具,信息,分析,状态,实时,命令,内存,总量,L

    查询linux内存命令?

    查询linux内存命令?,系统,情况,信息,工具,电脑,状态,命令,内存,发行,总量,查

    linux查内存命令6?

    linux查内存命令6?,情况,系统,信息,工具,数据,内存,命令,单位,环境,方法,查看

    数据库导出linux命令?

    数据库导出linux命令?,密码,数据,数据库,情况,地址,系统,工具,网上,名字,命

    linux性能检测命令?

    linux性能检测命令?,系统,情况,信息,状态,工具,实时,百分比,指标,分析,命令,

    linux修改内存命令?

    linux修改内存命令?,系统,信息,标准,工具,数据,在线,内存,命令,分区,大小,Lin

    linux命令与数据流?

    linux命令与数据流?,工作,地址,系统,信息,命令,目录,标准,网络,管理,常用命

    linux恢复数据库命令?

    linux恢复数据库命令?,工具,系统,软件,数据,盘中,密码,命令,备份,数据库,文

    linux历史命令内存?

    linux历史命令内存?,系统,情况,信息,数据,命令,内存,文件,磁盘,历史,内容,Lin

    linux储存命令数据?

    linux储存命令数据?,系统,工作,地址,信息,标准,命令,工具,实时,数据,分析,lin