我必须使用MIC的512位向量单元完成以下操作:
M->|b4|a4|b3|a3|b2|a2|b1|a1|
I->|d4|c4|d3|c3|d2|c2|d1|c1|
O-> O + |a4d4+b4c4|a4c4-b4d4|a3d3+b3c3|a3c3-b3d3|a2d2+b2c2|a2c2-b2d2|a1d1+b1c1|a1c1-b1d1|
我想到的方法类似于英特尔为SSE提出的方法,也适用于AVX:
使用_mm512_swizzle_pd()
函数形成:
m0 = | a4 | a4 | a3 | a3 | a2 | a2 | a1 | a1 |和m0_t = | b4 | b4 | b3 | b3 | b2 | b2 | b1 | b1 | in0 = | d4 | c4 | d3 | c3 | d2 | c2 | d1 | c1 |和in0_r = | c4 | d4 | c3 | d3 | c2 | d2 | c1 | d1 |
将上述两个相乘并使用类似于addsub_pd()的内容来表示MIC。但似乎并没有相应的内在。
有关如何实现这一目标的任何建议?
英特尔的MIC(Xeon Phi)也有几个FMA内在函数,如fmadd,fmsub,fnmadd,fnmsub,它们应该适应这种情况,我有以下两种方法:
'O' is the output register
Approach 1 :
1. _mm512_fmadd_pd(m0,in0,O);
2. Explicitly set m0_t using _mm512_set_pd() to make it: |b4|-b4|b3|-b3|b3|-b3|b1|-b1|
3. _mm512_fmadd_pd(m0_r,in0_r,O);
Approach 2:
1. _mm512_fmadd_pd(m0,in0,O);
2. _mm512_mask_fmadd_pd(m0_r,k1,in0_r,O); with k1=10101010
3. _mm512_mask_fnmadd_pd(m0_r,k2,in0_r,O); with k2=01010101
有更好的方法吗?这些方法有任何缺点吗?
答案 0 :(得分:1)
tmp = _mm512_mul_pd(mo_t,in_r);
tmp = _mm512_mask3_fmadd_pd(m0,in0,tmp,k1); with k1=10101010
res = _mm512_mask3_fmsub_pd(m0,in0,tmp,k2); with k2=01010101
为什么要使用_mm512_fnmadd_pd(v1,v2,v3)? 此内在函数的输出是(〜(v1 * v2)) - v3