【问题标题】:What is the fastest way to do a SIMD gather without AVX(2)?在没有 AVX(2) 的情况下进行 SIMD 收集的最快方法是什么?
【发布时间】:2013-11-02 16:15:12
【问题描述】:

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

a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3

分成四个向量a, b, c, d?

a: {a0, a1, a2, a3}
b: {b0, b1, b2, b3}
c: {c0, c1, c2, c3}
d: {d0, d1, d2, d3}

我不确定这是否相关,但在我的实际应用中,我有 16 个向量,因此 a0a1 在内存中相隔 16*4 字节。

【问题讨论】:

    标签: x86 sse simd sse4


    【解决方案1】:

    您需要的是 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
    

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

    【讨论】:

    • 你可能错过了我的问题中关于有 16 个向量而不是 4 个的句子。我应该使用像 4 个转置吗?
    • 确实 - 在不知道您打算如何处理所有这些向量的情况下,很难给出一个完整的解决方案,但是是的,您可以对剩余的 12 个向量重复上述步骤,每组 4 个。
    猜你喜欢
    • 2013-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2015-04-09
    相关资源
    最近更新 更多