在Cuda中写入大型未知大小数组?

在Cuda中写入大型未知大小数组?,cuda,Cuda,我有一个进程,我将数据发送到Cuda进行处理,它输出符合特定标准的数据。问题是我常常不知道输出数组的大小。我能做什么 我发送了几百行数据,并在Cuda上以超过20K种不同的方式进行处理。如果结果与我的一些规则匹配,那么我想保存结果。问题是我无法在Cuda中创建链接列表(如果可以,请告诉我),并且我卡上的内存很小,因此我考虑使用零拷贝让Cuda直接写入主机内存。这解决了我的内存大小问题,但仍然没有给我一种处理未知问题的方法 我最初的想法是计算出最大可能的结果,并对一个这样大小的数组进行malloc

我有一个进程,我将数据发送到Cuda进行处理,它输出符合特定标准的数据。问题是我常常不知道输出数组的大小。我能做什么

我发送了几百行数据,并在Cuda上以超过20K种不同的方式进行处理。如果结果与我的一些规则匹配,那么我想保存结果。问题是我无法在Cuda中创建链接列表(如果可以,请告诉我),并且我卡上的内存很小,因此我考虑使用零拷贝让Cuda直接写入主机内存。这解决了我的内存大小问题,但仍然没有给我一种处理未知问题的方法

我最初的想法是计算出最大可能的结果,并对一个这样大小的数组进行malloc。问题是它将是巨大的,并且大多数不会被使用(800行数据*20K可能的结果=数组中的1600万项..这是不可能的)


在Cuda中有没有更好的方法来处理可变大小的数组?我是编程新手,所以理想情况下它不会太复杂(尽管如果是,我愿意学习)。在内核代码中使用
malloc
分配堆内存是一项昂贵的操作(它强制CUDA驱动程序使用自定义堆大小初始化内核,并管理内核内部的内存操作)

通常,CUDA设备内存分配是影响程序性能的主要瓶颈。通常的做法是在开始时分配所有需要的内存,并尽可能长时间地重用它


我认为您可以创建足够大的缓冲区,并使用它来代替内存分配。在最坏的情况下,您可以将其包装以实现从该缓冲区的内存分配。在简单的情况下,您可以保留阵列中的最后一个空闲单元,以便下次将数据写入其中。

是的,CUDA和所有GPGPU的瓶颈是从主机到设备的传输

但是在内核中,总是使用所有已知大小的东西。 内核不能执行malloc。。。从平台的概念来看,这是非常非常奇怪的。 即使您在CUDA内核中有“for”循环,也要考虑20次您的方法是否是最优的,您一定在做真正复杂的算法。在并行平台上真的有必要吗? 如果你不这样做,你不会相信会出现什么问题

使用缓冲方法。您可以确定一些缓冲区大小,这更取决于CUDA要求(读取->硬件),然后是阵列。您在循环中调用内核,并从中上载、处理和检索数据。 一个,您的数据数组将完成,最后一个缓冲区将不满。 您可以将每个缓冲区的大小作为单个值传递(例如,指向int的指针),每个线程将与它的线程id进行比较,以确定是否可以获取某个值,或者是否超出了界限。 只有最后一个块会有发散。

这里有一个有用的链接:

您可以在内核函数中使用共享内存执行以下操作:

__global__ void dynamicReverse(int *d, int n)
{
  extern __shared__ int s[];
  .....
}
当您在主机上调用内核函数时,第三个参数是共享内存大小,精确地说是
n*sizeof(int)
dynamicReverse(dud,n)


此外,如果可能的话,最好将一个巨大的内核函数拆分成更多的内核函数,代码更少,执行起来更容易。

您可以在CUDA中创建一个链表——指针就是指针,就像在CPU上一样。但我不一定推荐这样做——指针在并行线程之间的追逐通常会导致不一致的内存访问,这可能会很昂贵。结果有多大?如果它们只是,比如说每个4字节(int或float),那么1600万个条目就不多了——只有64MB。在这种情况下,分配最大值可能是您的最佳选择——您可以在获得结果后将其复制到较小的缓冲区,并重用64MB的分配。如果结果是,比如说每个40或400个字节,那么你可以考虑其他的方法。@ HARRISM,它们非常小,它只是我正在测试的视频卡内存很小,我想弄清楚是否有一种有效的方法让列表按需增长。我可以在cuda内核仍在运行时复制到另一个缓冲区吗?或者必须这样做吗?有很多方法,但它们都会降低性能--这可能只是你付出的代价。一种方法是让内存大小成为您的限制器,并以较小的批量运行您的计算。另一种可能是使用设备端malloc,这可能并不像您想象的那么糟糕——在放弃之前尝试一下。我认为,正如所有事情一样,在优化之前让某些东西工作起来是取得良好进展的最佳方式。我不同意:CUDA设备内存分配通常不是CUDA程序性能的主要瓶颈。@harrism:你怎么看?我认为,主要的瓶颈出现在从主机到设备的边界上。这是其中之一=)细心的程序员尽可能避免在内部循环(或内核)中进行分配,无论是在主机上还是在设备上。内存传输(在主机和设备的边界)和内存带宽(设备或主机)是常见的瓶颈,但根据我的经验,内存分配在现实世界代码中是一个不太常见的瓶颈。@harrism:关于内存性能的评论可能指向设备端malloc/new,它不是特别快(或者不是我最后一次对其进行基准测试)。但设备端malloc也不是CUDA编程的一般情况。marina.k写道:“一般来说,CUDA设备内存分配是程序性能的主要瓶颈。”