【发布时间】:2017-12-04 11:47:00
【问题描述】:
我正在尝试通过使用 256 位向量(英特尔内在函数 - AVX)来提高我的代码的性能。
我有一个支持 SSE1 到 SSE4.2 和 AVX/AVX2 扩展的 I7 Gen.4(Haswell 架构)处理器。
这是我正在尝试增强的代码 sn-p:
/* code snipet */
kfac1 = kfac + factor; /* 7 cycles for 7 additions */
kfac2 = kfac1 + factor;
kfac3 = kfac2 + factor;
kfac4 = kfac3 + factor;
kfac5 = kfac4 + factor;
kfac6 = kfac5 + factor;
kfac7 = kfac6 + factor;
k1fac1 = k1fac + factor1; /* 7 cycles for 7 additions */
k1fac2 = k1fac1 + factor1;
k1fac3 = k1fac2 + factor1;
k1fac4 = k1fac3 + factor1;
k1fac5 = k1fac4 + factor1;
k1fac6 = k1fac5 + factor1;
k1fac7 = k1fac6 + factor1;
k2fac1 = k2fac + factor2; /* 7 cycles for 7 additions */
k2fac2 = k2fac1 + factor2;
k2fac3 = k2fac2 + factor2;
k2fac4 = k2fac3 + factor2;
k2fac5 = k2fac4 + factor2;
k2fac6 = k2fac5 + factor2;
k2fac7 = k2fac6 + factor2;
/* code snipet */
从英特尔手册中,我找到了这个。
整数加法 ADD 需要 1 个周期(延迟)。
8 个整数(32 位)的向量也需要 1 个周期。
所以我尝试过这样:
fac = _mm256_set1_epi32 (factor )
fac1 = _mm256_set1_epi32 (factor1)
fac2 = _mm256_set1_epi32 (factor2)
v1 = _mm256_set_epi32 (0,kfac6,kfac5,kfac4,kfac3,kfac2,kfac1,kfac)
v2 = _mm256_set_epi32 (0,k1fac6,k1fac5,k1fac4,k1fac3,k1fac2,k1fac1,k1fac)
v3 = _mm256_set_epi32 (0,k2fac6,k2fac5,k2fac4,k2fac3,k2fac2,k2fac1,k2fac)
res1 = _mm256_add_epi32 (v1,fac) ////////////////////
res2 = _mm256_add_epi32 (v2,fa1) // just 3 cycles //
res3 = _mm256_add_epi32 (v3,fa2) ////////////////////
但问题是这些因素将被用作表索引( table[kfac] ... )。所以我必须再次将因子提取为单独的整数。 不知道有没有办法呢??
【问题讨论】:
-
当你有这么多独立的添加发生时,延迟并不是什么大问题。每个时钟 4 条标量
add指令的吞吐量更为相关。如果k1fac2等已经在连续内存中,那么使用 SIMD 可能是值得的。否则,所有将它们输入/输出向量 regs 的洗牌和数据传输绝对不值得。 (并且 AVX2 收集在 Haswell 上很慢,否则您可以将其用于表加载。)
标签: c x86 simd intrinsics avx