accélération SSE en langage C++
Le
tmblues
Bonjour,
ayant écrit un programme qui requiert des calculs sur de grosses matrices (512*512 bytes), j'ai voulu optimiser mon calcul avec les fonctions SSE fournit par msdn (#include <emmintrin.h>). J'ai donc programmer une fonction permettant de faire des combinaisons entre les lignes de la matrice en travaillant 16 bytes par 16 bytes. La fonction fonctionne pour des matrices de taille strictement inférieure à 128*128 (la taille devant être un multiple de 16 c'est-à-dire 16*16, 32*32, 48*48, 64*64, 80*80, 96*96, 112*112). Dès que l'on dépasse 128 bytes, la fonction se comporte n'importe comment et affiche des valeurs fausses.
Y aurait-il un rapport avec la mémoire (lors de l'exécution aucune erreur mémoire ne s'affiche ).
voici le code de la fonction :
void CDecoder::linearCombination(char* row1, char* row2, char factor, char rowSize, char* result)
{
int nLoop = rowSize/16;
__m128i* pResult = (__m128i*) result;
__m128i* pRow1 = (__m128i*) row1;
__m128i* pRow2 = (__m128i*) row2;
__m128i row1cp;
__m128i resultcp;
__m128i un = _mm_set1_epi8(1);
__m128i zero = _mm_setzero_si128();
__m128i compare;
__m128i overflowing;
__m128i over = _mm_set1_epi8((char) 0x80);
__m128i poly = _mm_set1_epi8((char) 0x1D);
__m128i m1;
__m128i m2;
for(int i = 0; i<nLoop; i++)
{
__m128i mfactor = _mm_set1_epi8(factor);
row1cp = _mm_loadu_si128(pRow1);
resultcp = zero;
while(_mm_movemask_epi8(_mm_cmpeq_epi8(zero, row1cp)) != 65535)
{
compare = _mm_cmpeq_epi8(_mm_and_si128(un, row1cp), un);
m1 = _mm_and_si128(compare, mfactor);
resultcp = _mm_xor_si128(resultcp, m1);
overflowing = _mm_cmpeq_epi8(_mm_and_si128(mfactor, over), over);
mfactor = _mm_andnot_si128(un,_mm_slli_epi32(mfactor, 1));
m2 = _mm_and_si128(overflowing, poly);
mfactor = _mm_xor_si128(m2, mfactor);
row1cp = _mm_andnot_si128(over,_mm_srli_epi32(row1cp, 1));
}
*pResult = _mm_xor_si128(resultcp, *pRow2); //addition
pRow1++;
pRow2++;
pResult++;
}
}
merci d'avance
ayant écrit un programme qui requiert des calculs sur de grosses matrices (512*512 bytes), j'ai voulu optimiser mon calcul avec les fonctions SSE fournit par msdn (#include <emmintrin.h>). J'ai donc programmer une fonction permettant de faire des combinaisons entre les lignes de la matrice en travaillant 16 bytes par 16 bytes. La fonction fonctionne pour des matrices de taille strictement inférieure à 128*128 (la taille devant être un multiple de 16 c'est-à-dire 16*16, 32*32, 48*48, 64*64, 80*80, 96*96, 112*112). Dès que l'on dépasse 128 bytes, la fonction se comporte n'importe comment et affiche des valeurs fausses.
Y aurait-il un rapport avec la mémoire (lors de l'exécution aucune erreur mémoire ne s'affiche ).
voici le code de la fonction :
void CDecoder::linearCombination(char* row1, char* row2, char factor, char rowSize, char* result)
{
int nLoop = rowSize/16;
__m128i* pResult = (__m128i*) result;
__m128i* pRow1 = (__m128i*) row1;
__m128i* pRow2 = (__m128i*) row2;
__m128i row1cp;
__m128i resultcp;
__m128i un = _mm_set1_epi8(1);
__m128i zero = _mm_setzero_si128();
__m128i compare;
__m128i overflowing;
__m128i over = _mm_set1_epi8((char) 0x80);
__m128i poly = _mm_set1_epi8((char) 0x1D);
__m128i m1;
__m128i m2;
for(int i = 0; i<nLoop; i++)
{
__m128i mfactor = _mm_set1_epi8(factor);
row1cp = _mm_loadu_si128(pRow1);
resultcp = zero;
while(_mm_movemask_epi8(_mm_cmpeq_epi8(zero, row1cp)) != 65535)
{
compare = _mm_cmpeq_epi8(_mm_and_si128(un, row1cp), un);
m1 = _mm_and_si128(compare, mfactor);
resultcp = _mm_xor_si128(resultcp, m1);
overflowing = _mm_cmpeq_epi8(_mm_and_si128(mfactor, over), over);
mfactor = _mm_andnot_si128(un,_mm_slli_epi32(mfactor, 1));
m2 = _mm_and_si128(overflowing, poly);
mfactor = _mm_xor_si128(m2, mfactor);
row1cp = _mm_andnot_si128(over,_mm_srli_epi32(row1cp, 1));
}
*pResult = _mm_xor_si128(resultcp, *pRow2); //addition
pRow1++;
pRow2++;
pResult++;
}
}
merci d'avance

Poser une question


Jettes un oeil à Eigen2 (http://eigen.tuxfamily.org). Il me semble que
cette bibliothèque traite déjà ce problème avec brio : automatisati on
du SSE en fonction des règles de compilation. Dans le pire des cas, tu
auras une modélisation matricielle en métaprogrammation sur laquelle
tu pourras t'appuyer.