バイト値を合計するための SSE コードを作成しました。(VS2005.)
それは十分に単純であるため、非常にうまく機能します(そして高速です)。一部のサイズのアレイでのみクラッシュが発生します。そして、リリースモードでのみクラッシュします-デバッグでは決してクラッシュしません。多分誰かが「明らかな」バグを見ますか?どんな助けでも感謝します。
__int64 Sum (const unsigned char* pData, const unsigned int& nLength)
{
__int64 nSum (0);
__m128i* pp = (__m128i*)pData;
ATLASSERT( ( (DWORD)pp & 15 ) == 0 ); // pointer must point to address multiple of 16 (cache line)
__m128i zero = _mm_setzero_si128(),
a, b, c, d, tmp;
unsigned int i (0);
for ( ; i < nLength; i+=64) // 4-fach loop-unroll (x 16)
{
a = _mm_sad_epu8( *(pp++), zero);
b = _mm_sad_epu8( *(pp++), zero); // It crashes here.
c = _mm_sad_epu8( *(pp++), zero);
d = _mm_sad_epu8( *(pp++), zero);
// commenting the following line prevents the crash (???)
tmp = _mm_add_epi64( _mm_add_epi64( _mm_add_epi64( a, b ), c ), d);
a = _mm_srli_si128 ( tmp, 8 );
nSum += _mm_cvtsi128_si32( a ) + _mm_cvtsi128_si32( tmp );
}
// ... the rest
if (nLength % 64)
for (i -= 64; i < nLength; i++)
nSum += pData [i];
return nSum;
}
関数は次のように呼び出されます。
unsigned int nLength = 3571653; // One of the values that causes crash
unsigned char *pData = (unsigned char*) _aligned_malloc(nLength, 16);
Sum (pData, nLength);