【问题标题】:SSE Instructions: Byte+ShortSSE指令:字节+短
【发布时间】:2012-05-17 14:02:45
【问题描述】:

我有很长的字节数组需要添加到short(或int)类型的目标数组中。 是否存在这样的 SSE 指令?或者他们的套装?

【问题讨论】:

    标签: x86 sse instructions


    【解决方案1】:

    您需要将每个 8 位值的向量解包为两个 16 位值的向量,然后将它们相加。

    __m128i v = _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
    __m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); // vl = { 7, 6, 5, 4, 3, 2, 1, 0 }
    __m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); // vh = { 15, 14, 13, 12, 11, 10, 9, 8 }
    

    其中v 是一个 16 x 8 位值的向量,vlvh 是两个未压缩的 8 x 16 位值向量。

    请注意,我假设 8 位值是无符号的,因此当解压为 16 位时,高字节设置为 0(即无符号扩展)。

    如果您想对这些向量求和并获得 32 位结果,那么一个有用的技巧是使用带有 1 乘数的 _mm_madd_epi16,例如

    __m128i vsuml = _mm_set1_epi32(0);
    __m128i vsumh = _mm_set1_epi32(0);
    __m128i vsum;
    int sum;
    
    for (int i = 0; i < N; i += 16)
    {
        __m128i v = _mm_load_si128(&x[i]);
        __m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0));
        __m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0));
        vsuml = _mm_add_epi32(vsuml, _mm_madd_epi16(vl, _mm_set1_epi16(1)));
        vsumh = _mm_add_epi32(vsumh, _mm_madd_epi16(vh, _mm_set1_epi16(1)));
    }
    // do horizontal sum of 4 partial sums and store in scalar int
    vsum = _mm_add_epi32(vsuml, vsumh);
    vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 8));
    vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4));
    sum = _mm_cvtsi128_si32(vsum);
    

    【讨论】:

    • 请原谅我的无知,但你确定这是正确的吗?这个 vsum = _mm_madd_epi16(vh, _mm_set1_epi16(1));会抹去之前的 vsum 值。
    • @Alexandros:你说得对,我也看到了至少另一个错误——我想我写这个答案时一定很着急——我会尽快修复代码,但我目前正在旅行。
    • 谢谢保罗,不急。你过去帮了我很多,所以任何时候你都可以,修复它。旅途愉快!!
    • 其实不难修复 - 我现在无法测试它,但代码现在至少应该接近可行的解决方案。
    • 谢谢。我去看看
    【解决方案2】:

    如果您需要对字节向量进行符号扩展而不是零扩展,请使用pmovsxbw (_mm_cvtepi8_epi16)。与 unpack hi/lo 指令不同,您只能从 src 寄存器的低半/四分之一/八分之一 pmovsx。

    您可以直接从内存中 pmovsx,即使内在函数使这非常笨拙。由于在大多数 CPU 上,shuffle 吞吐量比负载吞吐量更受限制,因此执行两次 load+pmovsx 可能比执行一次 load + 3 shuffle 更可取。

    【讨论】:

      猜你喜欢
      • 2016-01-22
      • 2017-01-26
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 2012-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多