1

我是 OpenCL 的新手,试图找出 OpenCL 和哈希的优缺点。

比如说,我有一个简单的哈希函数:

public static uint GetHash(string str)
{
  uint s = 21; // seed
  foreach (char ch in str)
      s = (s + (uint)ch) * 10;
  return s;
}

(我知道这是一个可怕的哈希,但这只是一个例子)

现在假设我希望计算所有字符a-zA-Z0-9_的排列长度为 50,例如:

a
b
...
_
aa
ab
...
__

显然这是我需要计算的大量 (63^50) 哈希,因此我决定使用 OpenCL 和 GPU 计算。

我的问题是:OpenCL/GPU 计算会带来什么陷阱?我已阅读以下内容:

  1. 在 PCIe 总线上传输数据是 slooooooooowwwwwwwwwwwww
  2. 访问 GPU 上的全局内存是 sloooooooooooooowwwwww
  3. 经线中的所有“线程”必须执行相同的指令

这让我质疑在这种情况下 GPU 计算的有效性,因为在我看来,我需要使用以下方法之一:

  • 让每个线程计算自己的排列(违反#3,因为每个线程将有不同数量的增量要做)
  • 让每个线程执行一个影响所有其他线程的增量(违反 #2)
  • 计算 CPU 上的排列并将它们分派给 GPU(违反 #1,另外我基本上只是使用 GPU 来计算哈希......)

这些结论准确吗?如果不是,为什么,还有什么需要注意的吗?

4

1 回答 1

1

慢是一个相对的术语。但通常,您希望避免在 GPU 之间传输大量数据,或者换句话说,您必须通过在 GPU 上进行大量计算来使数据传输的成本“物有所值”您将结果转移回去。

因此,按照您目前所说的(据我所知)查看您的问题,您希望:

  1. 在主机(CPU)上生成每个可能的字符串
  2. 将原始字符串传输到 GPU
  3. 在 GPU 上并行计算这些字符串的哈希值
  4. 将计算的哈希值传输回主机(CPU)

这将运行不佳,因为哈希的计算在计算上相当简单,并且大部分时间将用于执行数据传输。

绝对要在 GPU 上生成字符串排列 - 这将避免 (2) 的成本。将这些拆分为工作项应该不会太难。如果你有一个基本字符串,例如'aaaa',并且每个后缀字符有 4 个维度,然后计算每个线程中的哈希(取决于哈希函数,如果前缀的哈希也可以节省大量成本) 'aaaa' 可以预先计算一次并重复使用)并将其放入输出中。

但我怀疑这种方法在将生成的哈希传输回主机时仍然会遇到瓶颈。如果之后您需要对散列做一些事情,例如检查与已知散列的相等性,您也可以在 GPU 上执行此操作,避免所有那些昂贵的数据传输,因为您只需要写回单个匹配(或者可能是几个匹配)字符串/结果哈希到全局内存而不是 63^50。

于 2013-10-26T06:03:14.123 回答