【问题标题】:How can I compare lots of vectors to each other in CUDA (efficiently)如何在 CUDA 中(有效地)比较大量向量
【发布时间】:2018-11-17 02:35:49
【问题描述】:

简介

我正在尝试编写一个将向量相互比较的程序。我需要它将每个向量与其他所有向量进行比较,并返回一个向量 c,其中 c[i] = a[i]/b[i]。所以我需要一个向量 C 用于集合中的每对向量。

代码 -- 简化

__global__
void compare_vectors(*a, *b, *c)  
    { c[ i ]  =  a[ i ] / b[ i ]  }

main()

    for(... all vectors...)  
        compare_vectors <<< grid, block >>> (n, n+1, result)

问题

我的问题是这样做比在 CPU 上执行要慢。每次我遍历for循环时,都会将两个比较向量复制到设备内存,然后将结果向量复制回主机内存。

我希望能够将每个向量与其他每个向量进行比较,但要高效地进行,然后一次将所有结果复制回来。我该如何构造它,以便没有太多对 cudaMemcpy 的调用?

信息
我是 CUDA 的新手,所以如果这非常明显,请多多包涵。

我浏览了许多教程,并四处搜索。但是所有其他示例似乎都在比较两个非常长的向量,而不是许多较小的向量。我做了很多搜索和研究,但我找不到这样做的方法。

我有大约 2,000 个向量要比较。并且每个向量都与其他向量进行比较。所以 ~2,000 ^2 比较。每个向量的长度为 100 - 200 个浮点数。

谢谢@MartinBonner 和@platinum95。把它画在一个网格上真的让事情变得更清楚了。

【问题讨论】:

  • 咳咳。 2000² 比较,很多 - 但比 2000! 少很多(大约 10**13000)。
  • 您的问题太小,无法在 GPU 上获利。不要浪费你的时间
  • 它既不是阶乘也不是平方,它是一个组合问题,由 2000!/(2!(2000-2)!) 给出,即 1999000。另外,说计算 1999000 浮点数无利可图200 维向量的划分听起来不真实。
  • @platinum95。目前尚不清楚 OP 是否要将 a 与 b 以及 b 与 a 进行比较。我假设他是(并且忽略了 a 和 a 毫无意义的事实 - 这意味着它实际上是 2000² - 2000。)
  • 操作。要查看它大致是正方形的,请绘制一个网格。用向量的名称标记每一行;用向量的名称标记每一列。网格上的每个点都是一个向量与一个向量(可能是同一个)的比较。网格上有 n² 个点。

标签: c++ optimization vector cuda


【解决方案1】:

您应该使用一次cudaMemcpy 调用将所有向量从 CPU 复制到设备内存,然后在一次内核调用中计算所有除法。在内核中,您可以为每个向量启动一个线程,然后该线程遍历所有其他向量并计算除法结果。如果您的 GPU 支持超过 2000 个线程,那么您应该重新设计算法,以便线程不迭代所有其他向量,而仅迭代其中的 1/10th,然后其他 9 个线程分别迭代向量的 1/10th

更新:您不需要将每一对从 CPU 传输到 GPU。只需创建一个空间足以容纳所有N 向量的数组,每个M 项长,然后在CPU 上将N*M 项一个接一个地复制到该数组,然后调用cudaMemcpy 在GPU 上获取该数组.

【讨论】:

  • 谢谢。 - 我不明白你的意思是让线程迭代超过向量的 1/10?你能详细说明吗? @SergeRogatch
  • @JohnMansell,不是向量的1/10th,而是您要与当前向量进行比较的所有其他向量的1/10th
  • 当您说“您应该使用一个 cudaMemcpy 调用将所有向量从 CPU 复制到设备内存”时。如何通过一次调用 cudaMemcpy 将它们全部转移?我应该将它们全部连接成一个长向量吗?我遇到的另一个问题是,由于它们是历史股票价格,所以并非所有向量的长度都相同。所以我不能按固定数量自动建立索引。我还必须传入每个向量的长度。 (如果它们都连接成一个向量)
  • 是的,您可以将它们全部连接成一个长向量。那么确实你也需要将长度传递给 CUDA。
【解决方案2】:

tl;dr:不要在(离散)GPU 上执行此操作

正如@talonmies 所暗示的,这个问题不适合将 GPU 用作协处理器。

您会看到,在 Intel 平台上,GPU 卡对主存的访问权限与 CPU 不同。数据必须通过 PCIe 总线发送给它,其带宽要低得多(典型值:12 GB/秒对 CPU 上的访问 30-40 GB/秒)。因此,虽然 GPU 执行计算的速度可能比 CPU 快,但只有当它们的“密度”(相对于您正在处理的数据量)足够高时,您才会开始看到好处。

在您的情况下,您将为要比较的每一对向量传输一个向量。即使 GPU 在 0 时间内立即执行所有计算,由于需要将结果复制回来,它在这个问题上仍然比 CPU 慢。

(另外,我真的怀疑你需要 n*(n-1)/2 个向量,这听起来很奇怪。)

【讨论】:

  • 感谢您详细说明为什么 GPU 可能不是一个好的选择。我没有考虑过传输速度。实际上,我将在 compare 函数中做更多的数学运算,但我试图尽可能地简化问题。我试图专注于无法有效发送大量小向量的主要问题。这会改变你的断言吗?我仍然想看看我是否可以通过使用 GPU 来缩短总程序时间。现在 CPU 大约需要 10 分钟才能在完整版本中运行 200 个向量。 @einpoklum
  • 他需要O(N*N*M) 复杂度,其中N 是向量的数量,M 是向量的长度。如果 N=2000M=200,这对于 GPU 来说是一个很好的案例。正如我在回答中解释的那样,他不需要传输O(N*N*M) 数据。他只需要在单个cudaMemcpy 中传输O(N*M)
  • @SergeRogatch:他说他需要每两个输入向量都有一个输出向量,即将N*(N-1)*M/2 元素传出。你不能只计算输入。
  • 你需要多少计算?除非有几个超然,否则不值得将其存储在内存中。动态重新计算更便宜
  • @RegisPortalez:这取决于。但基本上 - 很多。如果每个元素不是几十个,请不要打扰。
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 2015-08-30
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多