关于CUDA内核中内存分配的问题

时间:2011-05-12 20:51:25

标签: memory-management cuda dynamic-memory-allocation

嘿那里, 我的主机上有一个大小为SIZE*sizeof(double)的数组。我分配一个主机数组大小的设备指针,并将数组复制到设备。现在我将此设备数组dev_point传递给我的内核函数。每个线程需要修改传递的数组的某些值,然后使用新的数组值计算另一个_device__ - 函数(每个线程不同)。现在我想知道该怎么做?在我获得程序的完整CPU版本(序列代码)之前,我总是创建一个像double new_array[ SIZE ]这样的新数组,然后将原始数组中的数据复制到它,修改它并再次删除它。但是如何在CUDA中完成它,因为我无法从内核函数中分配内存。是否有可能使用线程的“本地”内存来存储新数组?或者我必须在调用我的内核函数之前分配一个大小为SIZE * number_of_total_threads * sizeof(double)的大数组,以便每个线程可以将修改后的数组存储在其中? 非常感谢提前!

编辑:完整说明! 好的,这里有一个关于我''当前'案例的更好的问题描述:在我的主机程序中我有一个数组,让我们说有300个值(取决于100到400之间的用户输入,让我们称之为变量numValues这是一个大小取决于程序参数,而不是硬编码到程序!)的双打。现在我希望每个内核执行完全取这个数组(它实际上被复制到GPU并作为指针传递给内核函数),将值更改为第n个元素(n =唯一标识符,从0到{{ 1}}),而所有其他数组元素保持不变。修改是对某个常量值的简单添加,也由用户传递给程序。然后调用一个定义为numValues传递修改后的数组的函数。

所以我想到的第一个解决方案就是我在这里问的那个:给每个线程(每个内核执行)一个自己的数组副本(我认为这可以在本地完成,但显然不能因为{{1}是特定于运行时),而不是让每个线程修改值__device__ double thefunction(double *ary)并用它来计算numValues

现在我在这里写下这个想法时想出了另一个想法:也许最好将数组放在常量或共享内存n中,以便每个线程将数组作为未修改的数组传递给{{1}但是指定thefunction作为索引ONCE的附加参数,关于要修改的元素和另一个参数thefunction关于要添加到thefunction - 元素的值。 我唯一想知道的是:如何将值int idx添加到double *add - 元素而不修改传递给函数的数组idx,因为这是传递的作为指针,我不想修改原始的!

谢谢!

2 个答案:

答案 0 :(得分:1)

如果单个GPU线程将使用数组,则可以将其分配到本地内存或全局内存中。本地内存在内核函数内声明,并且与在C中声明局部变量的工作方式完全相同。如果SIZE是整数常量而不是运行时值,则只能使用本地内存。否则,您将不得不使用全局内存。如你所说,要使用全局内存,请分配一个大数组。每个线程都会计算它将用作私有数组的大数组的偏移量。

但是,您应该考虑在GPU上重新组织算法。与CPU不同,其中一个线程可以使用大型缓存,GPU上的片上存储器由数百个线程共享。每个线程没有足够的片上存储器来容纳大型专用阵列,而片外存储器太慢而无法使用。 (例如,G80架构上的典型内核将使用16KB共享内存的256个线程,这将最大数组大小限制为64个字节。)是否可以并行化私有数组的计算?

答案 1 :(得分:1)

如果您只需要修改某些值,就像您说的那样,那么在计算单个结果所需的数据级别上,您应该只需要的本地副本一些的输入数据。理想情况下,该本地副本应保存在寄存器中,这是存储线程本地数据的最快位置。

如果一个结果所需的局部修改与另一个结果所需的局部修改之间存在数据依赖关系,通常的解决方案是将相互依赖的结果的计算分组到一个块中,并使用共享内存来保存修改后的数据,允许在该块内的线程之间进行数据交换。如果算法类似于递归关系,其中依次依赖于先前计算的数据,则需要一种新算法,因为这些类型的计算不能以任何有用的方式并行执行。

这是一个很好的答案,因为没有所涉及的代码和算法的细节,你将会得到答案。