2017-07-18 5 views
1

J'essaie de faire une multiplication matricielle en utilisant SSE. J'ai écrit un programme simple pour les matrices 4x4. Tout semble bien mais quand j'imprime le résultat, c'est quelques valeurs de poubelle. s'il vous plaît aider à comprendre le problème/s. Deuxièmement, le programme cesse de fonctionner quand je libère de la mémoire, pas une bonne fin de programme.Multiplication matricielle utilisant l'intrinsèque SSE

#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
#include <float.h> 
#include <xmmintrin.h> 

void main() { 
    float **a, **b, **c; 
    int a_r = 4, a_c = 4, b_c = 4, b_r = 4; 
    int i, j, k; 

    /* allocate memory for matrix one */ 
    a = (float **)malloc(sizeof(float) * a_r); 
    for (i = 0; i < a_c; i++) { 
     a[i] = (float *)malloc(sizeof(float) * a_c); 
    } 
    /* allocate memory for matrix two */ 
    b = (float **)malloc(sizeof(float) * b_r); 
    for (i = 0; i < b_c; i++) { 
     b[i] = (float *)malloc(sizeof(float) * b_c); 
    } 
    /* allocate memory for sum matrix */ 
    c = (float **)malloc(sizeof(float) * a_r); 
    for (i = 0; i < b_c; i++) { 
     c[i] = (float *)malloc(sizeof(float) * b_c); 
    } 
    printf("Initializing matrices...\n"); 

    //initializing first matrix 
    for (i = 0; i < a_r; i++) { 
     for (j = 0; j < a_c; j++) { 
      a[i][j] = 2; 
     } 
    } 
    // initializing second matrix 
    for (i = 0; i < b_r; i++) { 
     for (j = 0; j < b_c; j++) { 
      b[i][j] = 2; 
     } 
    } 
    /* initialize product matrix */ 
    for (i = 0; i < a_r; i++) { 
     for (j = 0; j < b_c; j++) { 
      c[i][j] = 0; 
     } 
    } 

    int count = 0; 
    /* multiply matrix one and matrix two */ 
    for (i = 0; i < a_r; i++) { 
     for (j = 0; j < a_c; j++) { 
      count = 0; 
      __m128 result = _mm_setzero_ps(); 
      for (k = 0; k < 4; k += 4) { 
       __m128 row1 = _mm_loadu_ps(&a[i][k]); 
       __m128 row2 = _mm_loadu_ps(&b[k][j]); 
       result = _mm_mul_ps(row1, row2); 

       for (int t = 1; t < 4; t++) { 
        __m128 row3=_mm_loadu_ps(&a[t * 4]); 
        __m128 row4=_mm_loadu_ps(&b[i][t]); 
        __m128 row5 = _mm_mul_ps(row3,row4); 
        result = _mm_add_ps(row5, result); 
       } 
       _mm_storeu_ps(&c[i][j], result); 
      } 
     } 
    } 
    printf("******************************************************\n"); 
    printf ("Done.\n"); 

    for (i = 0; i < a_r ; i++) { 
     for (j = 0; j < b_c; j++) { 
      printf ("%f ", c[i][j]); // issue here when I print results. 
     } 
     printf("\n"); 
    }  // Here program stops working. 

    /*free memory*/ 
    for (i = 0; i < a_r; i++) { 
     free(a[i]); 
    } 
    free(a); 
    for (i = 0; i < a_c; i++) { 
     free(b[i]); 
    } 
    free(b); 
    for (i = 0; i < b_c; i++) { 
     free(c[i]); 
    } 
    free(c); 
} 

Veuillez regarder l'adresse imprimée pour la matrice de sortie. comment obtenir des adresses alignées, j'ai _aligned_malloc, mais toujours pas aligné.

enter image description here

+0

pourrait être parce que vos tableaux attribués ne sont pas alignés * * – meowgoesthedog

+0

@spug toute idée comment aligner ou vérifier Aligement? – Sarmad

+2

Que signifie _stops working_? Est-ce qu'il s'est écrasé? Ou geler? Que se passe-t-il lorsque vous l'examinez dans le débogueur? Quel compilateur utilisez-vous? – Useless

Répondre

3

L'allocation pour la matrice des pointeurs indirects est incorrect. il faut lire:

a = (float **)malloc(sizeof(float*) * a_r); 

Un moyen plus sûr d'écrire ces allocations est la suivante:

a = malloc(sizeof(*a) * a_r); 

Notez que vous pouvez affecter les matrices 2D directement:

float (*a)[4][4] = malloc(sizeof(*a)); 

Ou mieux, comme Cody gris suggéré:

float (*a)[4][4] = _aligned_malloc(sizeof(*a)); 

_aligned_malloc est une fonction non standard qui garantit un alignement correct des opérandes SSE.

Si vous ne fait probablement pas besoin même d'affecter ces matrices avec malloc():

float a[4][4]; 

Mais avec ce dernier choix, vous devez vous assurer un bon alignement pour les opérations SSE pour réussir.

Le reste du code a d'autres problèmes:

  • void main() est incorrect. Il doit être int main(void)

  • La deuxième opérande de la matrice doit être transposée afin que vous puissiez lire plusieurs valeurs à la fois. La deuxième charge deviendrait:

    __m128 row2 = _mm_loadu_ps(&b[j][k]); 
    
  • La phase de sommation semble également incorrecte. Et le magasin final est certainement incorrect, devrait juste être:

    c[i][j] = sum; 
    
+0

Vous devriez probablement utiliser '_aligned_malloc' dans le code SIMD. –

+0

@CodyGray: réponse mise à jour. – chqrlie