【问题标题】:How to Multiply 2 16 bit vectors and store result in 32 bit vector in sse?如何将 2 个 16 位向量相乘并将结果存储在 sse 中的 32 位向量中?
【发布时间】:2016-06-23 12:41:15
【问题描述】:

由于溢出问题,我需要将 2 个 16 位向量相乘,并希望得到 32 位向量的输出,如下所示。

   A = [ 1, 2, 3, 4, 5, 6, 7, 8]
   B = [ 1, 3, 5, 6, 8, 9, 10 ,12 ]

   C1= [ 1*1 + 2*3, 3*5, 4*6]
   c2= [ 5*8, 6* 9, 7*10, 8*12 ]

我能够做到这一点,首先将 A 和 B 分成 32 位向量,然后使用下面的乘法函数

static inline __m128i muly(const __m128i &a, const __m128i &b)
{
    __m128i tmp1 = _mm_mul_epu32(a, b); /* mul 2,0*/
    __m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(a, 4), _mm_srli_si128(b, 4)); /* mul 3,1 */
    return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE(0, 0, 2, 0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE(0, 0, 2, 0))); /* shuffle results to [63..0] and pack */
}

但我认为这并不高效,我们可以使用_mm_mullo_epi16 来提高效率。有人可以建议/发布代码来实现这一点吗?

【问题讨论】:

    标签: c++ sse simd sse2


    【解决方案1】:

    是的,你可以这样做:

    static inline void muly(__m128i &vh, __m128i &vl,           // output - 2x4xint32_t
                            const __m128i v0, const __m128i v1) // input  - 2x8xint16_t
        const __m128i vhi = _mm_mulhi_epi16(v0, v1);            // mul lo
        const __m128i vlo = _mm_mullo_epi16(v0, v1);            // mul hi
        vh = _mm_unpackhi_epi16(vlo, vhi);                      // interleave results
        vl = _mm_unpacklo_epi16(vlo, vhi);
    }
    


    请注意,对于 16x16 乘法,您可能需要考虑使用定点乘法。这种方法通常用于 DSP 和图像处理任务,例如滤波。它比完整的 16x16->32 乘法效率高得多,并且还避免了数据加宽和缩小到 16 位的需要。

    见:__m128i _mm_mulhrs_epi16 (__m128i a, __m128i b)

    【讨论】:

    • 再次感谢保罗
    • 嗨,保罗,如果我理解正确的话 __mm_mulhrs_epi16 将两个 16 位相乘产生 32 位温度,然后将其截断为 16 位,对吗?我使用 32 位结果的原因是因为我想在截断之前累积所有高斯系数乘法结果,因为我观察到是否添加所有 32 位高斯乘法,然后仅在乘法期间截断或截断。
    • 好的 - 如果 16 位中间项不够准确,那可能是个问题。如果您最终生成 8 位像素组件,尽管我认为它已经足够好了,除非您的过滤器非常大(?)。无论如何,继续使用完整的 32 位方法 - 一旦第一个版本工作,您可以随时考虑进一步优化。
    • 感谢您对这个保罗的帮助。是的,过滤器在某些情况下非常大。无论如何,我第一次尝试让它工作我现在有了显着的改进,如果需要更多改进,我将进一步分析这一点。再次感谢
    猜你喜欢
    • 2015-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多