【发布时间】:2016-10-09 09:05:21
【问题描述】:
我正在尝试使用 cuBLAS 在 GPU 上计算 C = A*A',我发现 rank-k 更新 cublasDsyrk 的运行速度比一般矩阵-矩阵乘法例程 cublasDgemm 慢约 5 倍。
这让我很惊讶;我认为syrk 会更快,因为它是一段更专业的代码。这是不合理的期望吗?我做错了吗?
计时代码
最终我正在编写 CUDA 代码以编译为 MATLAB 的 MEX 文件,因此很抱歉没有提供完整的工作示例(会有很多无关的代码用于与 MATLAB 对象争吵)。
我知道这可能不是最好的方法,但我正在使用 clock() 来计算代码运行所需的时间:
// Start of main function
clock_t tic = clock();
clock_t toc;
/* ---- snip ---- */
cudaDeviceSynchronize();
toc = clock();
printf("%8d (%7.3f ms) Allocated memory on GPU for output matrix\n",
toc-tic,1000*(double)(toc-tic)/CLOCKS_PER_SEC);
// Compute the upper triangle of C = alpha*A*A' + beta*C
stat = cublasDsyrk(handle, CUBLAS_FILL_MODE_UPPER, CUBLAS_OP_N,
M, N, &alpha, A, M, &beta, C, M);
toc = clock();
printf("%8d (%7.3f ms) cublasDsyrk launched\n",
toc-tic,1000*(double)(toc-tic)/CLOCKS_PER_SEC);
cudaDeviceSynchronize();
toc = clock();
printf("%8d (%7.3f ms) cublasDsyrk completed\n",
toc-tic,1000*(double)(toc-tic)/CLOCKS_PER_SEC);
/* ----- snip ----- */
运行时
在 [12 x 500,000] 随机矩阵(列主要存储)上运行的输出:
911 ( 0.911 ms) Loaded inputs, initialized cuBLAS context
1111 ( 1.111 ms) Allocated memory on GPU for output matrix
1352 ( 1.352 ms) cublasDsyrk launched
85269 ( 85.269 ms) cublasDsyrk completed
85374 ( 85.374 ms) Launched fillLowerTriangle kernel
85399 ( 85.399 ms) kernel completed
85721 ( 85.721 ms) Finished and cleaned up
将syrk 调用替换为
stat = cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_T, M, M, N,
&alpha, A, M, A, M, &beta, C, M);
整个过程运行得更快:
664 ( 0.664 ms) Loaded inputs, initialized cuBLAS context
796 ( 0.796 ms) Allocated memory on GPU for output matrix
941 ( 0.941 ms) cublasDgemm launched
16787 ( 16.787 ms) cublasDgemm completed
16837 ( 16.837 ms) Launched fillLowerTriangle kernel
16859 ( 16.859 ms) kernel completed
17263 ( 17.263 ms) Finished and cleaned up
我尝试了一些其他尺寸的矩阵;有趣的是,当矩阵的行数很少时,速度差异似乎最为明显。在 100 行时,gemm 仅快 2 倍,而在 1000 行时则稍慢(这是我一直以来的预期)。
其他详情
我使用的是 CUDA Toolkit 7.5,GPU 设备是 NVIDIA Grid K520(Kepler,计算能力 3.0)。我在 Amazon EC2 g2.x2large 实例上运行。
【问题讨论】: