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
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
PEM
Le #21684121
On May 5, 7:29 am, tmblues
Bonjour,

ayant écrit un programme qui requiert des calculs sur de grosses matric es
(512*512 bytes), j'ai voulu optimiser mon calcul avec les fonctions SSE f ournit
par msdn (#include de faire des combinaisons entre les lignes de la matrice en travaillant 1 6 bytes
par 16 bytes. La fonction fonctionne pour des matrices de taille strictem ent
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épa sse 128
bytes, la fonction se comporte n'importe comment et affiche des valeurs f ausses.

Y aurait-il un rapport avec la mémoire (lors de l'exécution aucune er reur
mémoire ne s'affiche ).
voici le code de la fonction :

void CDecoder::linearCombination(char* row1, char* row2, char factor, cha r
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(ze ro, row1cp)) != 65535)
                {
                        compare = _mm_cmpeq_epi 8(_mm_and_si128(un, row1cp), un);                
                        m1 = _mm_and_si128(comp are, mfactor);            
                        resultcp = _mm_xor_si12 8(resultcp, m1);
                        overflowing = _mm_cmpeq _epi8(_mm_and_si128(mfactor, over), over);
                        mfactor = _mm_andnot_si 128(un,_mm_slli_epi32(mfactor, 1));  
                        m2 = _mm_and_si128(over flowing, poly);                                  
                        mfactor = _mm_xor_si128 (m2, mfactor);                                          
                        row1cp = _mm_andnot_si1 28(over,_mm_srli_epi32(row1cp, 1));
                }
                *pResult = _mm_xor_si128(resultcp, *pRo w2);    //addition

                pRow1++;
                pRow2++;
                pResult++;
        }

}

merci d'avance



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.
Publicité
Poster une réponse
Anonyme