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



我有一个 100 万列 x 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 示例在 2 个向量上进行 sgemm 操作来尝试这种计算,但是当我在大量向量上进行时,最终有传输时间删除了 GPU 加速的好处。

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

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

你能管道化你的操作吗?换句话说,您的循环是否由以下内容组成?

  • CPU>GPU 复制
  • 图形处理
  • GPU>CPU 副本

要进行管道处理,您将使用(例如)4 个单独的(按顺序)命令队列,在每个队列上向 GPU 发出非阻塞传输,在每个队列上发出内核执行,并按该顺序在每个队列上发出 GPU>CPU 副本。您必须保证两个缓冲区在等待之前都有效(稍后介绍)。这将允许 GPU 在进行后续内存传输的同时开始计算。

此外,切勿使用阻塞内存传输,始终使用非阻塞。每隔这么多次(8?)次传输,获取一个用于GPU>CPU副本的事件对象,但如果这不是第一次迭代,请先等待最后一个事件对象。这将限制队列并允许重复使用缓冲区,但重叠操作会使传输和计算重叠。我们正在等待 8 次迭代前的传输,因此我们不会耗尽队列。管理队列深度很重要,过多的工作项会导致 GUI 滞后和工作项饥饿。

相关内容

  • 没有找到相关文章

最新更新