问题描述
我正在尝试创建点积的高效 SIMD 版本,以实现 FIR 滤波器 i16 类型的 2D 卷积。
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
#[target_feature(enable = "avx2")]
unsafe fn dot_product(a: &[i16],b: &[i16]) {
let a = a.as_ptr() as *const [i16; 16];
let b = b.as_ptr() as *const [i16; 16];
let a = std::mem::transmute(*a);
let b = std::mem::transmute(*b);
let ms_256 = _mm256_mullo_epi16(a,b);
dbg!(std::mem::transmute::<_,[i16; 16]>(ms_256));
let hi_128 = _mm256_castsi256_si128(ms_256);
let lo_128 = _mm256_extracti128_si256(ms_256,1);
dbg!(std::mem::transmute::<_,[i16; 8]>(hi_128));
dbg!(std::mem::transmute::<_,[i16; 8]>(lo_128));
let temp = _mm_add_epi16(hi_128,lo_128);
}
fn main() {
let a = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
let b = [0,15];
unsafe {
dot_product(&a,&b);
}
}
I] ~/c/simd (master|…) $ env RUSTFLAGS="-C target-cpu=native" cargo run --release | wl-copy
warning: unused variable: `temp`
--> src/main.rs:16:9
|
16 | let temp = _mm_add_epi16(hi_128,lo_128);
| ^^^^ help: if this is intentional,prefix it with an underscore: `_temp`
|
= note: `#[warn(unused_variables)]` on by default
warning: 1 warning emitted
Finished release [optimized] target(s) in 0.00s
Running `target/release/simd`
[src/main.rs:11] std::mem::transmute::<_,[i16; 16]>(ms_256) = [
0,16,25,36,49,64,81,100,121,144,169,196,225,]
[src/main.rs:14] std::mem::transmute::<_,[i16; 8]>(hi_128) = [
0,]
[src/main.rs:15] std::mem::transmute::<_,[i16; 8]>(lo_128) = [
64,]
虽然我从概念上理解 SIMD,但我不熟悉确切的指令和内在函数。
我知道我需要将两个向量相乘,然后水平求和,然后将它们减半并使用指令将两个较小的向量垂直相加。
我发现madd指令应该在乘法后立即进行这样的求和,但不确定如何处理结果。
如果使用 mul 而不是madd,我不确定使用哪些指令来进一步减少结果。
欢迎任何帮助!
附注 我已经尝试过packed_simd,但它似乎对稳定锈不起作用。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)