没有AVX(2)进行SIMD收集的最快方法是什么?

orl*_*rlp 6 x86 sse simd sse4

假设我有SSE到SSE4.1,但没有AVX(2),加载这样的打包内存布局的最快方法是什么(所有32位整数):

a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3
Run Code Online (Sandbox Code Playgroud)

进入四个向量a, b, c, d

a: {a0, a1, a2, a3}
b: {b0, b1, b2, b3}
c: {c0, c1, c2, c3}
d: {d0, d1, d2, d3}
Run Code Online (Sandbox Code Playgroud)

我不知道这是否是相关与否,但在我的实际应用中我有16个向量,因此a0a1相距16个*4字节的内存.

Pau*_*l R 9

你需要的是4个载荷,然后是4x4转置:

#include "emmintrin.h"                       // SSE2

v0 = _mm_load_si128((__m128i *)&a[0]);       // v0 = a0 b0 c0 d0 
v1 = _mm_load_si128((__m128i *)&a[16]);      // v1 = a1 b1 c1 d1
v2 = _mm_load_si128((__m128i *)&a[32]);      // v2 = a2 b2 c2 d2
v3 = _mm_load_si128((__m128i *)&a[48]);      // v3 = a3 b3 c3 d3

// 4x4 transpose

w0 = _mm_unpacklo_epi32(v0, v1);             // w0 = a0 a1 b0 b1 
w1 = _mm_unpackhi_epi32(v0, v1);             // w1 = c0 c1 d0 d1 
w2 = _mm_unpacklo_epi32(v2, v3);             // w2 = a2 a3 b2 b3
w3 = _mm_unpackhi_epi32(v2, v3);             // w3 = c2 c3 d2 d3
v0 = _mm_unpacklo_epi64(w0, w2);             // v0 = a0 a1 a2 a3
v1 = _mm_unpackhi_epi64(w0, w2);             // v1 = b0 b1 b2 b3
v2 = _mm_unpacklo_epi64(w1, w3);             // v2 = c0 c1 c2 c3
v3 = _mm_unpackhi_epi64(w1, w3);             // v3 = d0 d1 d2 d3
Run Code Online (Sandbox Code Playgroud)

注意:这可能比使用AVX2收集的负载更有效,因为它们为每个元素生成一个读取周期,这使得它们在访问模式未知或难以使用时才真正有用.

  • 事实上,如果不知道您打算如何处理所有这些向量,就很难给出完整的解决方案,但是,您可以对其余 12 个向量(每组 4 个)重复上述步骤。 (2认同)