我是CUDA的新手,正在尝试对大量数组进行一些处理。每个数组都是一个大约1000个字符的数组(不是字符串,只是存储为字符),最多可以有100万个,所以要传输大约1 GB的数据。这个数据已经全部加载到内存中,并且我有一个指向每个数组的指针,但我认为我不能依赖所有数据在内存中的顺序,所以我不能只通过一次调用来传输它。
我目前第一次使用推力,基于我的解决方案类型this message ...我创建了一个带有静态调用的结构,它分配了所有内存,然后每个构造函数都复制了数组,我有一个转换调用,它接受带有指向设备数组的指针的结构。
我的问题是,这显然非常慢,因为每个数组都是单独复制的。我想知道如何更快地传输这些数据。
在this question中(问题大部分是无关的,但我认为用户正在尝试做类似的事情)talonmies建议他们尝试使用zip迭代器,但我不知道这将如何帮助转移大量的数组。
在编写这个问题时我也刚刚发现了cudaMemcpy2DToArray和cudaMemcpy2D,所以也许这些就是答案,但我不会立即看到它们是如何工作的,因为它们似乎都没有把指针作为输入指针... < / p>
欢迎任何建议......
答案 0 :(得分:1)
这样做的一种方法是像marina.k建议的那样,只在您需要的时候批量转移。既然你说每个数组只包含大约1000个字符,你可以将每个字符分配给一个线程(因为在Fermi上我们可以为每个块分配1024个线程)并让每个数组由一个块处理。在这种情况下,您可以在一次调用中将所有数组转移到一个“圆形” - 您可以使用FORTRAN样式,在其中创建一个巨大的数组并获得“第三个”1000个字符数组的第5个元素去:
third_array[5] = big_array[5 + 2*1000]
这样第一个1000个char数组构成了big_array的前1000个元素,第二个1000个char数组构成了big_array的第二个1000个元素,等等?在这种情况下,你的字符在内存中是连续的,你可以只在一个memcpy中移动一个内核启动时要处理的集合。然后,只要启动一个内核,就可以在CPU端重新填充big_array,并将其异步复制到GPU。
在每个内核中,你可以简单地处理1个块内的每个数组,这样块N就可以处理第(n-1)个第 - 千个元素,直到d_big_array的千分之五(你将所有这些字符复制到的地方)。
答案 1 :(得分:1)
你尝试过固定内存吗?这可以在某些硬件配置上提供相当大的加速。
答案 2 :(得分:1)
尝试异步,您可以将相同的作业分配给不同的流,每个流处理一小部分日期,同时进行转移和计算
这是代码:
cudaMemcpyAsync(
inputDevPtr + i * size, hostPtr + i * size, size, cudaMemcpyHostToDevice, stream[i]
);
MyKernel<<<100, 512, 0, stream[i]>>> (outputDevPtr + i * size, inputDevPtr + i * size, size);
cudaMemcpyAsync(
hostPtr + i * size, outputDevPtr + i * size, size, cudaMemcpyDeviceToHost, stream[i]
);