我有一个 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 滞后和工作项饥饿。