CUDA上的2D数组

我想在CUDA动态分配全局2D数组。 我怎样才能做到这一点?

在我的主要部分,我在一个循环中调用我的Kernel 。 但在我调用内核之前,我需要在GPU上分配一些内存。 在内核调用之后,从GPU向CPU发送单个整数以通知问题是否已解决。
如果问题没有解决,我将不会释放旧内存,因为还需要它,我应该为GPU分配新内存并再次调用内核。

显示了一个sudocode:

 int n=0,i=0; while(n==0) { //allocate 2d memory for MEM[i++] //call kernel(MEM,i) // get n from kernel } __global__ void kernerl(Mem,int i) { Mem[0][5]=1; Mem[1][0]=Mem[0][5]+23;//can use this when MEM[1] is allocated before kernel call } 

有什么建议? 谢谢。

两个开放注释 – 使用动态分配的2D数组在CUDA中是一个坏主意,并且在循环中执行重复的内存分配也不是一个好主意。 两者都会导致不必要的性能损失。

对于主机代码,如下所示:

 size_t allocsize = 16000 * sizeof(float); int n_allocations = 16; float * dpointer cudaMalloc((void **)&dpointer, n_allocations * size_t(allocsize)); float * dcurrent = dpointer; int n = 0; for(int i=0; ((n==0) && (i>> (dcurrent,.....); // whatever you do after the kernel } 

是优选的。 在这里,您只需调用一次cudaMalloc,并将偏移量传递给分配,这样可以在循环内部释放内存分配和管理。 循环结构也意味着你无法无休止地运行并耗尽所有GPU内存。

在二维arrays问题本身,有两个原因,这是一个坏主意。 首先,分配要求具有N行的2Darrays需要(N + 1)个cudaMalloc调用和主机设备存储器副本,这是缓慢而丑陋的。 其次,在内核代码中,为了获取数据,GPU必须执行两次全局内存读取,一次用于指针间接获取行地址,然后一次用于从行中获取数据。 这比这个替代方案要慢得多:

 #define idx(i,j,lda) ( (j) + ((i)*(lda)) ) __global__ void kernerl(float * Mem, int lda, ....) { Mem[idx(0,5,lda)]=1; // MemMem[0][5]=1; } 

它使用索引到1D分配。 在GPU内存中,交易非常昂贵,但FLOPS和IOPS都很便宜。 单个整数乘法 – 加法是最有效的方法。 如果您需要访问先前内核调用的结果,只需将偏移量传递给之前的结果并在内核中使用两个指针,如下所示:

 __global__ void kernel(float *Mem, int lda, int this, int previous) { float * Mem0 = Mem + this; float * Mem1 = Mem + previous; } 

高效的分布式内存程序(和CUDA实际上是一种分布式内存编程)在一段时间后开始看起来像Fortran,但这是你为便携性,透明度和效率付出的代价。

希望这有帮助。

好吧,你可以像在CPU上完成一样。

 unsigned xSize = 666, ySize = 666; int **h_ptr = (int**)malloc(sizeof(int*) * xSize); int **d_ptr = NULL; cudaMalloc( &d_ptr, xSize ); for(unsigned i = 0; i < xSize; ++i) { cudaMalloc( &h_ptr[i], ySize ); } cudaMemcpy( &d_ptr, &h_ptr, sizeof(int*) * xSize, cudaMemcpyHostToDevice ); free( h_ptr ); 

......并且免费相似

 int **h_ptr = (int**)malloc(sizeof(int*) * xSize); cudaMemcpy( &h_ptr, &d_ptr, sizeof(int*) * xSize, cudaMemcpyDeviceToHost ); for(unsigned i = 0; i < xSize; ++i ) { cudaFree( h_ptr[i] ); } cudaFree( d_ptr ); free( h_ptr ); 

但是你应该记住,每次访问这个数组的单元格都需要两次访问GPU全局内存。 因此,内存访问速度将比使用1darrays慢两倍。

编辑:
我试图帮助你提供一个例子,在这个例子中,展平arrays,你可以达到同样的效果,但是伙伴告诉我这不是你要求的。
所以这里有另一篇文章告诉你如何在CUDA中分配2d数组。