3

unsigned short dst[16][16]行列とより大きなunsignedcharsrc[m][n]行列があります。

次に、srcマトリックスにアクセスし、 SSE2またはSSE3を使用して16x16サブマトリックスをdstに追加する必要があります。

以前の実装では、合計値が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 ビット値の 2 つのベクトルにアンパックし、これらのベクトルを両方とも宛先に追加する必要があります。

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 に答える