2017-02-08 27 views
0

我是cuda新手,所以我希望我的问题不完全脱离基础。 我想在全局设备内存上创建一个数组,但我只知道它在我的主要功能中间有多大(但在我访问设备之前)。从主CUDA声明设备变量

因为我不知道大小我无法将代码之前声明: 设备 myArr,该[]

所以我想创造主,d_myArr指针,然后使用cudaMalloc d_myArr的( ,arrSize)在设备上分配内存,但我从来没有真正在设备上声明变量。

我没有看到将d_Arr发送到我的内核的原因,因为它只会存在于该内核中(我认为?),我只是希望变量作为全局变量存在于我的设备中,并可以被不同的内核访问。

我可以在main声明一个设备变量吗?如在:

int main(){ 
    . 
    . 
    __device__ myArr[size]; 
    . 
    . 
} 

如果是这样,它由于某种原因泄露(因为我找不到任何人这样做)。如果这是不允许的,我能做些什么呢?我看到有人提到cudaMemcpyToSymbol,但我无法弄清楚它是否与我想要的完全相同,如果是的话,我会很高兴如果有人能够准确解释如何使用它来实现我所需要的。

在侧面的问题,我也有一个常数变量,我想在我的设备和主机上都存在。现在我只是宣布了两次,一次用设备,一次没有,有没有更好的方法来做到这一点?

回答

2

这不起作用。

  1. __device__变量必须在全球范围内声明。
  2. 在编译时必须知道与__device__变量关联的分配大小。

取而代之,只要使用cudaMalloc为变量分配空间,一旦您知道所需的分配大小。该方法允许动态分配全局变量。 __device__方法只允许静态分配全局变量。

像这样:

int main(){ 
    // ... 
    int *d_data; 
    cudaMalloc(&d_data, size*sizeof(int)); 
    // ... 
    kernel1<<<...>>>(d_data,...); 
    // ... 
    kernel2<<<...>>>(d_data,...); 
    // ... 
} 

它是完全合法的这样的动态分配的全局变量传递给一个以上的内核我上面示出,并且将数据或修改通过上述kernel1放在那里(如果任何)将在上面kernel2中运行的代码可见,例如我已经展示过。

对于常量变量问题,您提到的方法是合理的。如果您拥有编译时未知的常量数据,那么这是一个明智的方法(您也可以使用__constant__而不是__device__进行调查)。如果在另一方面,你有恒定的数据在编译时已知的,则无论是使用

#define MYCONSTANT 123 

constant int myconstant=123; 

在全局范围(即main外)将允许这样的定义可以在主机或设备代码中同等使用,无需申报或管理两次。对于POD数据类型(例如int,float,double等),这最后一种方法可以很好地工作,但不适用于像struct这样的复杂类型。

+0

感谢您的回应! 就这样,我可以确保我正确理解,因为我在设备中分配了内存,它不会丢失,即使我不使用cudaMemcpy来回信息,我的第二个内核中的s_sata将与我的第一个内核的结束,对吧?所以只要我重新发送指向我所有内核的指针,它们都可以引用该变量,否则,如果我不重新发送该变量,它仍然存在于分配的内存中,但我没有引用来访问它。 –

+0

是的,一旦你用'cudaMalloc'分配了设备内存,它就是** persistent **,直到你对它调用一个'cudaFree'操作(或者直到你的应用程序终止)为止。它的行为与其他任何内存一样。一旦你写了一些东西,后续的操作可以看到写了什么,不管是后续的内核还是后续的'cudaMemcpy'操作。 –