Halide CUDA GPU SGEMM实施

时间:2017-01-27 14:59:44

标签: halide

我正在尝试构建基于Halide的图像处理算法,该算法在其某个阶段需要SGEMM功能。

我发现Halide有两个矩阵乘法实现:

  1. 线性代数算法(apps/linear_algebra folder
  2. CUDA矩阵乘法应用程序(apps/cuda_mat_mul folder
  3. 对于大小为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) - 图片看起来很相似:

    • cuBlas时间:0.003174
    • Halide linalg SGEMM时间:0.042568
    • Halide cuda_mat_mul时间:0.006792

    基准测试代码来自apps / cuda_mat_mul / runner.cpp,但是将迭代次数从10更改为100以获得更精确的时序

    如何更改计划以使其与TitanX上的cuBlas附近的性能一起使用?

    更新:测试Ubuntu 16.4,LLVM 3.8,Halide - 最新版本来自git,Cuda 8

0 个答案:

没有答案