【问题标题】:How best to transfer a large number of arrays of chars to the GPU?如何最好地将大量字符数组传输到 GPU?
【发布时间】:2012-05-14 20:31:41
【问题描述】:

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

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

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

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

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

欢迎提出任何建议...

【问题讨论】:

  • 如果您不需要立即在内核中使用所有这些内存。您可以使用同步复制操作复制其中的一部分,而使用异步复制操作复制其他部分。这种复制机制可以采用你的算法吗?
  • 嗯,我不确定,该算法的工作原理是每个数组都可以独立处理,这就是我尝试在 GPU 上并行化它的原因。我想这取决于 GPU 上可用的最大线程数,然后是的,我可以传输那么多数组,然后在处理这些数组时复制其他数组。
  • 我最终决定最好的方法就是根本不使用推力,而只是将内存(意味着我必须复制它)重新组织成一个连续的数组可以一次性全部转移。感谢那些回复的人。

标签: cuda gpu thrust


【解决方案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 个元素(您将所有这些字符复制到其中)。

【讨论】:

  • 嗯,我想我可能不够清楚,但是处理需要在每个数组的基础上完成,所以我认为每个数组需要 1 个线程。至于 1 个巨大的数组,是的,理想情况下我会这样做,问题是这些数组在我执行此处理时已经加载到内存中并且它们没有像那样加载......而且我真的不想复制它们,因为它大约有 1 GB 的内存......但我认为我可能不得不改变它们最初的加载方式,以便它们作为 1 个大数组加载。
【解决方案2】:

你试过固定内存吗?这可能会在某些硬件配置上提供相当大的加速。

【讨论】:

    【解决方案3】:

    试试异步,你可以将同一个作业分配给不同的流,每个流处理一小部分日期,同时进行传输和计算
    这是代码:

    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]
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2021-05-09
      • 1970-01-01
      相关资源
      最近更新 更多