使用SSE或SSE3在ushort数组中添加uchar值

时间:2012-11-09 18:07:00

标签: c++ c parallel-processing sse ushort

我有一个无符号短dst [16] [16]矩阵和一个更大的无符号char src [m] [n]矩阵。

现在我必须使用SSE2SSE3在src矩阵中访问并向dst添加一个16x16子矩阵。

在较早的实现中,我确信我的求和值永远不会超过256,所以我可以这样做:

for (int row = 0; row < 16; ++row)
{
    __m128i subMat = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(src));
    dst[row] = _mm_add_epi8(dst[row], subMat);
    src += W; // Step to the next row I need to add
}

其中W是到达所需行的偏移量。这段代码有效,但现在我在src中的值更大,求和可能大于256,所以我需要将它们存储为ushort。

我尝试了以下内容,但它不起作用。

for (int row = 0; row < 16; ++row)
{
    __m128i subMat = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(src));
    dst[row] = _mm_add_epi16(dst[row], subMat);
    src += W; // Step to the next row I need to add
}

我该如何解决这个问题?

修改

谢谢保罗,但我认为你的抵消是错误的。我已经尝试过你的解决方案,似乎子矩阵的行被添加到错误的dst行中。我希望正确的解决方案是:

for (int row = 0; row < 32; row += 2)
{
    __m128i subMat = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(src));
    __m128i subMatLo = _mm_unpacklo_epi8(subMat, _mm_set1_epi8(0));
    __m128i subMatHi = _mm_unpackhi_epi8(subMat, _mm_set1_epi8(0));
    dst[row] = _mm_add_epi16(dst[row], subMatLo);
    dst[row + 1] = _mm_add_epi16(dst[row + 1], subMatHi);
    src += W;
}

1 个答案:

答案 0 :(得分:3)

您需要将16 x 8位值的向量解包为两个8 x 16位值的向量,然后将这两个向量添加到目标位置:

for (int row = 0; row < 16; ++row)
{
    __m128i subMat = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(src));
    __m128i subMatLo = _mm_unpacklo_epi8(subMat, _mm_set1_epi8(0));
    __m128i subMatHi = _mm_unpackhi_epi8(subMat, _mm_set1_epi8(0));
    dst[row] = _mm_add_epi16(dst[row], subMatLo);
    dst[row + 1] = _mm_add_epi16(dst[row + 1], subMatHi);
    src += W;
}