You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust自动向量化优化规则咨询:多段代码向量化差异疑问

Rust自动向量化的行为分析

测试环境:MacBook Pro M1,编译命令:cargo rustc --bin rust-playground -- -C opt-level=3 --emit=llvm-ir,通过LLVM-IR中的向量指令(如add <4 x i32>、mul <4 x i32>)判断是否被自动向量化。


案例1:简单求和未被向量化

调用代码(前3个案例共用):

fn main() {
    let a = [
        1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6,
        7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4,
        5, 6, 7, 8,
    ];
    println!("{:?}", auto_vec(&a));
}

目标函数代码:

pub fn auto_vec(a: &[i32]) -> i32 {
    let mut p = 0;
    for i in a {
        p += i;
    }
    p
}

现象:LLVM-IR中无向量加法指令,未被自动向量化。
原因:单变量求和的计算密度低,M1的NEON标量加法延迟更低,编译器认为标量实现的性能更优;同时该函数是独立对外暴露的,编译器无法确定输入数组的最小长度,出于保守选择不触发向量化。


案例2:同时求和与平方和被向量化

目标函数代码:

pub fn auto_vec(a: &[i32]) -> i32 {
    let mut p = 0;
    let mut q = 0;
    // can see some instructions like 'add <4 x i32>' and 'mul <4 x i32>'
    for i in a {
        p += i;
        q += i * i;
    }
    q - p
}

现象:LLVM-IR中出现add <4 x i32>和mul <4 x i32>向量指令,被自动向量化。
原因:循环内同时进行两个独立的计算任务(求和、平方和),NEON向量单元可以并行处理这两个操作,整体吞吐量提升明显。此时向量化的收益远超过额外开销,编译器因此触发自动向量化。


案例3:计算结果未使用时未被向量化

目标函数代码:

pub fn auto_vec(a: &[i32]) -> i32 {
    let mut p = 0;
    let mut q = 0;
    // can't see some instructions like 'add <4 x i32>' or 'mul <4 x i32>'
    for i in a {
        p += i;
        q += i * i;
    }
    // do not access p and q
    0
}

现象:LLVM-IR中无向量指令,未被自动向量化。
原因:编译器的*死代码消除(DCE)*优化会识别到p和q的计算结果未被使用,直接将整个循环代码完全删除,自然不会生成任何向量化指令。查看LLVM-IR会发现,函数仅保留返回0的逻辑。


案例4:函数内联后部分向量化

代码:

fn main() {
    // can see store <4 x i32>
    let a = [
        1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6,
        7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4,
        5, 6, 7, 8,
    ];
    let mut p = 0;
    let mut q = 0;
    // can't see add <4 x i32> or mul <4 x i32>
    for i in a {
        p += i; 
        q += i * i;
    }
    println!("{:?}", q - p);
}

现象:LLVM-IR中出现store <4 x i32>但无向量加法/乘法指令。
原因:函数内联后,编译器能识别到数组a是编译期常量,直接进行常量折叠优化——提前计算出q-p的最终结果,循环代码被完全消除,因此看不到向量运算指令;而数组初始化时,由于是固定长度的常量数组,被优化为向量存储指令以提升初始化效率。


数组长度对向量化的影响

当数组过短时,编译器不会进行向量化优化,原因是:向量化需要额外开销,比如循环头尾的边界处理(处理无法被向量长度整除的元素)、向量寄存器的初始化与加载存储等。如果数组长度太小,这些额外开销会超过向量化带来的性能提升,因此编译器会选择标量实现,避免得不偿失。一般编译器会设置一个阈值(通常为向量宽度的2-4倍),只有当数组长度超过该阈值时才会考虑向量化。


内容的提问来源于stack exchange,提问作者doki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:55:01