代码之家  ›  专栏  ›  技术社区  ›  Anopt

如何让Rust自动矢量化生成VMULSS的VMULPS集成?

  •  0
  • Anopt  · 技术社区  · 2 年前

    我有一个 function 以将大小为MxK和KxN的两个16x16矩阵相乘在一起。教科书矩阵乘法。编译时使用 --release -C target-cpu=native 在支持AVX512的CPU上。

    其中一根轴已展开。看起来,自动矢量化应该很容易看到一个在内存中连续的浮点乘法,将其打包到 ymm / zmm 寄存器并使用进行压缩乘法 vmulps ,但它反而生成 vmulss 因此,它明显变慢了。

    相关代码片段:

            for h in 0..16 {
                let aval = a[(v * n) + h];
                let bvals = &b[(h * n)..(h * n + 16)];
                g0 += aval * bvals[0];
                g1 += aval * bvals[1];
                g2 += aval * bvals[2];
                g3 += aval * bvals[3];
                g4 += aval * bvals[4];
                g5 += aval * bvals[5];
                g6 += aval * bvals[6];
                g7 += aval * bvals[7];
                g8 += aval * bvals[8];
                g9 += aval * bvals[9];
                g10 += aval * bvals[10];
                g11 += aval * bvals[11];
                g12 += aval * bvals[12];
                g13 += aval * bvals[13];
                g14 += aval * bvals[14];
                g15 += aval * bvals[15];
            }
    

    虽然我知道这有点 命中和未命中 优化器是否会抓住机会生成更好的代码,我很困惑为什么优化器不会做上面预期的事情。

    有趣的是,下面的替代方案,似乎是未优化的代码,导致优化器生成4倍更快的代码,使用 vmulps , vaddps ,等等。优化器在这段代码中看到了上面代码中没有看到的内容???

    pub fn matmul(a: &[f32], b: &[f32], r: &mut [f32], m: usize, k: usize, n: usize) {
        let a = &a[0..(m * k)];
        let b = &b[0..(k * n)];
        for t in 0..k {
            for y in 0..m {
                for x in 0..n {
                    r[(y * n) + x] += a[(y * n) + t] * b[(t * n) + x];
                }
            }
        }
    }
    

    这是在不使用unsafe或显式使用intrinsic的情况下生成自己的快速矩阵多重函数的努力的一部分。不幸的是,上面的内容让我觉得很难用rustc进行逐步优化,而且这将是徒劳的。

    0 回复  |  直到 2 年前