0

我有一个 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库中

4

1 回答 1

0

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

你能流水线化你的操作吗?换句话说,您的循环是否包含以下内容?

  • CPU->GPU 拷贝
  • GPU 计算
  • GPU->CPU 拷贝

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

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

于 2012-06-14T13:53:42.133 回答