3

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

现在我必须访问 src 矩阵并使用SSE2SSE3向 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;
}
4

1 回答 1

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;
}
于 2012-11-10T10:58:40.560 回答