我正在尝试构建基于Halide的图像处理算法,该算法在其某个阶段需要SGEMM功能。
我发现Halide有两个矩阵乘法实现:
对于大小为1024x1024的矩阵:
首先它们在CPU(Intel i7)和Fermi GPU(GF 540M)上表现相当不错,CPU时间接近OpenBlas,而Fermi GPU时间接近cuBlas(约18ms),但这种实现方式比Maxwell GPU(TitanX)上的cuBlas - 5 ms vs 0.4 ms。 与费米的cuBlas相比,第二个实现(cuda_mat_mul)慢了3倍 - 大约57ms vs 18 ms,Maxwell GPU与cuBlas相比慢了2倍 - 1 ms vs 0.4 ms
正如我所见 - Halide可以为Fermi GPU生成最佳代码,但无法在Maxwell上快速运行。据我所知,SGEMM功能是许多具有正确调度的FusedMultiplyAdd,但我找不到任何可以使其在Maxwell上快速工作的最佳时间表。
我能想象的最快的Halide代码放在cuda_mat_mul文件夹中,时间表是:
Func prod("prod");
RDom r(0, size);
prod(x, y) += A(x, r) * B(r, y);
Var xi, yi, xio, xii, yii, xo;
Func out = prod.in();
out.bound(x, 0, size)
.bound(y, 0, size)
.tile(x, y, xi, yi, 8*32, 8)
.split(xi, xio, xii, 32)
.reorder(xio, yi, xii, x, y)
.unroll(xio)
.unroll(yi)
.gpu_blocks(x, y).gpu_threads(xii);
prod.compute_at(out, xii)
.unroll(x)
.unroll(y)
.update()
.unroll(r.x, 2)
.reorder(y, x, r.x)
.unroll(x)
.unroll(y);
B.in()
.compute_at(prod, y)
.vectorize(B.in().args()[0])
;
我也尝试使用更大的矩阵(2048x2048) - 图片看起来很相似:
基准测试代码来自apps / cuda_mat_mul / runner.cpp,但是将迭代次数从10更改为100以获得更精确的时序
如何更改计划以使其与TitanX上的cuBlas附近的性能一起使用?
更新:测试Ubuntu 16.4,LLVM 3.8,Halide - 最新版本来自git,Cuda 8