使用gpgpu进行大量矢量计算的最佳方法?

时间:2012-06-12 15:59:59

标签: java opencl gpgpu jocl jcuda

我有一个100万列×100万行的矩阵。

我的算法需要做:

Matrix m  = Matrix(rows,cols)
for (colB: cols){
  vector currColA = m.getcolumn(colA)

  for (colB: cols){
    vector currColB = m.getcolumn(colB)
    result = currColA.dotProduct(colB)
    return result;
}}

或者您也可以说:

Vectors [] v  = Vectors[]

for (i: v.length){
  vector v1 = v[i]

  for (i: v.length){
    vector v2 = v[i]
    result = v1.dotProduct(v2)
    return result;
}}

我的问题:为这个问题分配内存和初始化内存的正确方法是什么:

- 我应该为完整矩阵分配内存,用完整矩阵初始化它,然后运行算法?
- 或者我应该为矢量列表分配内存,然后遍历此列表? - 或者其他??

我担心的是,我希望尽可能减少到gpu的传输时间。我已经通过修改JCublas hello world example对2个向量的sgemm操作尝试了这种计算,但是当我在大量向量上执行时,最终传输时间删除了gpu加速的好处。

THX! PS:实现可以在任何Java库中

1 个答案:

答案 0 :(得分:0)

听起来你正在强制执行一次一个限制。 CPU-> GPU复制,等待,计算,GPU-> CPU复制,等待。大多数人都没有意识到内存副本可能导致的隐式等待。

您可以管理您的运营吗?换句话说,你的循环是否包含以下内容?

  • CPU-> GPU copy
  • GPU计算
  • GPU-> CPU copy

要对此进行管道传输,您将使用(例如)4个单独(按顺序)命令队列,在每个队列上向GPU发出非阻塞传输,在每个队列上发出内核执行,并发出GPU->按顺序在每个队列上复制CPU。您必须保证两个缓冲区在等待之前保持有效(稍后描述)。这将允许GPU在后续的内存传输过程中开始计算。

此外,永远不要使用阻止内存传输,始终使用非阻塞。每隔这么多(8?)次传输,获取GPU-> CPU复制的事件对象,但如果不是第一次迭代,则先等待最后一个事件对象。这将限制您的队列并允许您重用缓冲区,但重叠操作会使传输和计算重叠。我们正在等待8次迭代前的转移,所以我们没有排空队列。管理队列深度很重要,过多的工作项会导致滞后的GUI和工作项目的饥饿。