2

我是 CUDA 新手,正在尝试对大量数组进行一些处理。每个数组是一个大约 1000 个字符的数组(不是字符串,只是存储为字符),最多可以有 100 万个字符,因此要传输大约 1 gb 的数据。这些数据已经全部加载到内存中,并且我有一个指向每个数组的指针,但我认为我不能依赖所有数据在内存中的顺序,所以我不能一次调用就全部传输。

我目前第一次尝试使用推力,并基于此消息的解决方案 ...我使用分配所有内存的静态调用创建了一个结构,然后每个单独的构造函数复制该数组,我有一个转换调用,它接收带有指向设备数组的指针的结构。

我的问题是这显然非常慢,因为每个数组都是单独复制的。我想知道如何更快地传输这些数据。

这个问题中(这个问题大部分是不相关的,但我认为用户正在尝试做类似的事情)talonmies 建议他们尝试使用 zip 迭代器,但我看不出这将如何帮助传输大量数组。

我在写这个问题时也刚刚发现了 cudaMemcpy2DToArray 和 cudaMemcpy2D ,所以也许这些就是答案,但我没有立即看到它们是如何工作的,因为它们似乎都没有将指向指针的指针作为输入......

欢迎任何建议...

4

3 回答 3

1

一种方法是按照 marina.k 的建议,仅在需要时对传输进行批处理。由于您说每个数组仅包含大约 1000 个字符,因此您可以将每个字符分配给一个线程(因为在 Fermi 上,我们可以为每个块分配 1024 个线程)并让每个数组由一个块处理。在这种情况下,您可以在一次调用中传输一个“回合”的所有数组 - 您可以使用 FORTRAN 样式,在其中创建一个巨大的数组并获取“第三个”1000 字符数组的第 5 个元素去:

third_array[5] = big_array[5 + 2*1000]

这样前 1000 个字符数组构成 big_array 的前 1000 个元素,第二个 1000 个字符数组构成 big_array 的后 1000 个元素,等等。在这种情况下,您的字符将在内存中是连续的,您可以移动要处理的集合,只需在一个 memcpy 中启动一个内核即可。然后,一旦启动一个内核,就在 CPU 端重新填充 big_array 并将其异步复制到 GPU。

在每个内核中,您可以简单地处理 1 个块内的每个数组,以便块 N 处理第 (N-1) 个元素,直到 d_big_array 的第 N 个元素(您将所有这些字符复制到其中)。

于 2012-05-14T23:22:32.110 回答
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]
);
于 2012-05-22T08:55:54.927 回答
1

你试过固定记忆吗?这可以在某些硬件配置上提供相当大的加速。

于 2012-05-15T20:29:30.423 回答