Ani*_*rta 4 c++ intrinsics avx
我试图围绕_mm256_shuffle_pd和_mm256_permute_pd内在函数如何工作.我似乎无法预测其中一项操作的结果.
首先,对于_mm_shuffle_ps一切都很好.我得到的结果是我期待的结果.例如:
float b[4] = { 1.12, 2.22, 3.33, 4.44 };
__m128 a = _mm_load_ps(&b[0]);
a = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 1, 2));
_mm_store_ps(&b[0], a);
// 3.33 2.22 1.12 4.44
Run Code Online (Sandbox Code Playgroud)
所以一切都在这里.现在我想用__m256d尝试这个,这是我目前在我的代码中使用的.从我发现的_mm256_shuffle_ps/pd内在函数的工作方式不同.
我的理解是控制掩码应用了两次.第一次在128位的前半部分,第二次在最后的128位.前两对控制位用于从第一矢量中选择(并将值存储在第一和第二字以及结果矢量的第五和第六字中),而最高位对选择第二矢量.例如:
float b[8] = { 1.12, 2.22, 3.33, 4.44, 5.55, 6.66, 7.77, 8.88 };
__m256 a = _mm256_load_ps(&b[0]);
a = _mm256_shuffle_ps(a, a, 0b00000111);
_mm256_store_ps(&b[0], a);
// 4.44 2.22 1.12 1.12 8.88 6.66 5.55 5.55
Run Code Online (Sandbox Code Playgroud)
这里我期望的结果(我实际得到的)是 { 4.44, 2.22, 1.12, 1.12, 8.88, 6.66, 5.55, 5.55 }
这应该如下工作:
(对不起,我画画很糟糕).并且对于使用最高两对(因此00 00)并填充缺失空间的第二矢量(在这种情况下再次)进行相同的操作.
我认为_mm256_shuffle_pd会以同样的方式工作.因此,如果我想要第一个双倍,我将不得不移动00空间和01空间来正确构造它.
例如:
__m256d a = _mm256_load_pd(&b[0]);
a = _mm256_shuffle_pd(a, a, 0b01000100);
_mm256_store_pd(&b[0], a);
// 1.12 1.12 4.44 3.33
Run Code Online (Sandbox Code Playgroud)
我原以为这会输出{1.12,1.12,3.33,3.33}.在我的脑海中,我从第一个向量中获取00 01(1.12)和00 01 {3.33},从第二个向量中获取相同的向量,并且它是相同的向量.
我已经尝试了很多控制面具的组合,我只是无法围绕如何使用它,也无法找到以我理解的方式解释它的地方.
所以我的问题是:_mm256_shuffle_pd如何工作?我怎样才能得到与_mm_shuffle_ps(a,a,_MM_SHUFFLE(3,0,2,1))相同的结果,包括四个双打和一个随机播放(如果可能的话)?
shufps需要所有8位立即仅4个元素,每个元素有4个可能的源.因此它没有空间来增长256位,唯一的选择是在两个通道中复制相同的shuffle.
但128位shufpd只有2个元素,每个元素有2个源,因此2 x 1位.所以AVX版本总共使用4位,每个通道使用2位.(它不是交叉路口,所以它没有128位那么强大shufps.)
http://felixcloutier.com/x86/SHUFPD.html上有完整的文档,包含图表和详细的伪代码.英特尔的内在指南_mm256_shuffle_pd具有相同的伪代码.
AVX2 http://felixcloutier.com/x86/VPERMPD.html(_mm256_permute_pd,又名_mm256_permute4x64_pd)是交叉路口,并且使用它的直接方式就像128位shufps一样:四个2位选择器.
唯一的交叉2源shuffle是vperm2f128(_mm256_permute2f128_pd),直到AVX512F引入更精细的粒度vpermt2pd和vpermt2ps(和等效的整数shuffle.
AVX1没有任何小于128位的粒度的交叉混洗,甚至不是单源版本.如果你需要一个,你必须建立它vinsertf128或vperm2f128+车道内洗牌.
因此,使用AVX将3D矢量保持在SIMD矢量中比float使用128位矢量更差. http://fastcpp.blogspot.com/2011/04/vector-cross-product-using-sse-code.html可能比标量更快,但是如果你为SIMD设计数据布局,它会比你做得更糟.
使用单独的阵列连续的x[],y[]和z[]这样你就可以并行,没有洗牌做4倍交叉产品,走的FMA指令的优势. 使用SIMD并行执行多个向量,而不是加速单个向量.
见链接https://stackoverflow.com/tags/sse/info,尤其是https://deplinenoise.wordpress.com/2015/03/06/slides-simd-at-insomniac-games-gdc-2015/这解释数据布局问题很好,以及使用SIMD进行矢量化的循环级别.
| 归档时间: |
|
| 查看次数: |
498 次 |
| 最近记录: |