如何在CUDA中比较大量的向量(有效)

时间:2018-06-07 08:46:06

标签: c++ optimization vector cuda

简介

我试图编写一个将矢量相互比较的程序。我需要它将每个向量与每个其他向量进行比较,并返回向量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循环时,两个比较向量都被复制到Device存储器,然后结果向量被复制回主机存储器。

我希望能够将每个矢量与每个其他矢量进行比较,但要有效地进行,然后立即复制所有结果。我如何构建这个,以便没有这么多的cudaMemcpy调用?

信息
我是CUDA的新手,所以如果这是非常明显的话,请保持优雅。

我已经完成了很多教程,并且四处寻找。但所有其他例子似乎都在比较两个非常长的向量,而不是很多较小的向量。我做了很多搜索和研究,但我找不到办法。

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

谢谢@MartinBonner和@ platinum95。在网格上绘制它确实使事情变得更加清晰。

2 个答案:

答案 0 :(得分:4)

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

更新:您不需要将每对从CPU转移到GPU。只需创建一个数组,其空间足以容纳所有N个向量,每个M项长,然后在CPU副本N*M项上一个接一个地连接到此数组,然后调用{{1}在GPU上也可以获得这个数组。

答案 1 :(得分: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个向量,听起来很奇怪。)