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

如何让Rust编译器生成AVX2指令?我的分块函数为何无宽乘法?

为什么手动分块的mul2函数没有生成AVX2宽乘法指令?

你写的两个函数逻辑本质完全一致:

fn mul1(xs: &[i32], ys: &[i32]) -> Vec<i32> {
    // Assuming xs.len() == ys.len()
    xs.iter().zip(ys.iter()).map(|(x, y)| x * y).collect()
}

fn mul2(xs: &[i32], ys: &[i32]) -> Vec<i32> {
    const CHUNK_SIZE: usize = 8;
    // Assuming xs.len() == ys.len() and xs.len() % CHUNK_SIZE == 0
    let chunks = xs.chunks_exact(CHUNK_SIZE).zip(ys.chunks_exact(CHUNK_SIZE));
    let result_chunks = chunks.map(|(c1, c2)| c1.into_iter().zip(c2.into_iter()).map(|(x, y)| x * y));
    result_chunks.flatten().collect()
}

问题出在哪?

mul2只是把数组做了表面上的分块,但内部依然是逐个元素遍历相乘,和mul1的执行逻辑没有任何区别。Rust编译器的自动向量化优化不需要你手动拆分数组,它会自行识别连续的元素级运算并生成SIMD指令;手动分块的操作完全是多余的,不会给编译器提供额外的优化线索。

怎么真正利用AVX2指令?

如果要手动控制AVX2的使用,不能依赖普通迭代器,需要直接使用AVX2的内在函数(intrinsics),或者借助SIMD相关库。以下是用标准库intrinsics实现的示例:

use std::arch::x86_64::*;

fn mul_avx2(xs: &[i32], ys: &[i32]) -> Vec<i32> {
    assert_eq!(xs.len(), ys.len());
    assert_eq!(xs.len() % 8, 0);
    let mut result = vec![0; xs.len()];

    unsafe {
        for i in (0..xs.len()).step_by(8) {
            // 加载8个i32到AVX2寄存器
            let x = _mm256_loadu_si256(xs.as_ptr().add(i) as *const __m256i);
            let y = _mm256_loadu_si256(ys.as_ptr().add(i) as *const __m256i);
            // 批量乘法:8个i32同时相乘
            let mul_result = _mm256_mullo_epi32(x, y);
            // 将结果写回内存
            _mm256_storeu_si256(result.as_mut_ptr().add(i) as *mut __m256i, mul_result);
        }
    }

    result
}

补充:关于自动向量化

你的mul1函数在开启-O2或-O3优化后,编译器会自动生成AVX2指令。查看汇编时要确保开启了优化模式,Debug模式下编译器不会进行向量化这类激进优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 21:12:35