我看到 CUBLAS 可能是用于单个大型矩阵乘法或加法等的有效算法包。但在常见的设置中,大多数计算都是依赖的。所以下一步依赖于上一步的结果。
这会导致一个问题,因为输出矩阵必须与 CUBLAS 例程中的输入矩阵不同(因为输入矩阵是 const ),所以要花费大量时间来分配空间并为这些临时矩阵从设备复制数据。
那么是否可以做诸如乘法(A,A,B)之类的事情,其中第一个参数是输出矩阵,第二个/第三个是输入矩阵,以避免额外的内存操作时间?还是有更好的解决方法?
非常感谢 !
不,不可能像gemm
使用 CUBLAS 那样执行就地操作(事实上,我不知道有任何并行的 BLAS 实现可以保证这样的操作会起作用)。
话虽如此,这条评论:
.... 大量时间花在 malloc 空间和将数据从设备复制到设备以用于这些临时矩阵。
让我觉得你可能忽略了显而易见的事情。虽然有必要为临时矩阵分配空间,但在使用此类分配时当然没有必要执行设备到设备的内存复制。这个:
// If A, B & C are pointers to allocations in device memory
// compute C = A*B and copy result to A
multiply(C, A, B);
cudaMemcpy(A, C, sizeA, cudaMemcpyDeviceToDevice);
// now A = A*B
可以替换为
multiply(C, A, B);
float * tmp = A; A = C; C = tmp;
IE。您只需要在主机上交换指针即可执行相当于设备到设备内存复制的操作,而无需 GPU 时间成本。这不能在所有情况下都使用(例如,有一些就地块操作可能仍需要显式内存传输),但在大多数情况下,可以避免显式设备到设备内存传输。
如果使用 CUBLAS 进行大型密集操作的内存成本限制了您的应用程序,请考虑研究处理大型密集矩阵的“核心外”方法。
您可以预先分配一个缓冲区矩阵,并在 mat-mul 操作之前将输入矩阵 A 复制到缓冲区。
Memcopy(buff, A);
Multiply(A, buffer, B);
通过重用缓冲区,您不需要每次都分配缓冲区,并且每个 mat-mul 的开销将只有一个 mem 副本。当您的矩阵足够大时,开销的时间成本将占很小的一部分,可以忽略不计。