Cette page présente plusieurs algorithmes de multiplication de matrices.
Le but est de multiplier 2 matrices m1 et m2 de taille NxN. Le résultat est placé dans r.
Le langage utilisé est le C.

La plupart des algorithmes a été récupérée sur Internet et les noms des auteurs figurent quand c'est possible.

Si vous avez des méthodes originales, des idées pour améliorer la vitesse, pour des matrices quelconques ou particulières, de grande taille ou petite, n'hésitez pas à m'envoyer vos sources. Les nouveaux algorithmes seront comparés aux anciens et inclus dans la liste.

Les test de vitesses sont avec la configuration suivante:

algorithmes temps (s)
mul_1 24.335
mul_2 24.455
mul_3 24.305
mul_4 24.465
mul_5 4.747
mul_6 5.097
mul_7 32.527
mul_8 32.507
mul_9 15.482
mul_10 24.335
mul_11 24.335
mul_12 24.315
mul_13 24.355
mul_14 12.157
mul_15 10.405
mul_16 12.167

Ces temps peuvent beaucoup varier d'une machine à une autre, en fonction de la taille du cache, de l'agencement des routines dans le programme et de la mémoire disponible. Faire des tests sur votre machine peut donner un nouvel ordre.

Voici les codes des algorithmes. Le fichier complet est MATRICE.CPP.
Les codes ont été vérifiés avec Purify de Rational.

#define TYPE double // Type des éléments des matrices
#define N 720 // Taille des matrices

#define M 720

#define P 720

TYPE m1[N][N]; // Matrices: r = m1 . m2
TYPE m2[N][N];

TYPE r[N][N];

TYPE a[N][M];
TYPE b[M][P];

TYPE p[N][P];

//-------------------------------------------------------------------------------------------------
// r = 0

// p = 0

void clear(void)
{

 int

  l,

  c;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

   r[l][c] = 0.0;

 for(l = 0; l < N; l++)

  for(c = 0; c < P; c++)

   p[l][c] = 0.0;

}

//-------------------------------------------------------------------------------------------------
// Vérifie que r = m1 . m2

int testr(void)

{

 int

  l,

  c,

  k,

  t = 1;

 double

  v;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

  {

   v = 0.0;

   for(k = 0; k < N; k++)

    v += m1[l][k] * m2[k][c];

   t &= r[l][c] == v;

  }

 if(t)
  cout << "Ok" << " - ";

 else

  cout << "Erreur" << " - ";

 return t;

}

//-------------------------------------------------------------------------------------------------
// Vérifie que p = a . b

int testp(void)

{

 int

  l,

  c,

  k,

  t = 1;

 double

  v;

 for(l = 0; l < N; l++)
  for(c = 0; c < P; c++)

  {

   v = 0.0;

   for(k = 0; k < M; k++)

    v += a[l][k] * b[k][c];

   t &= p[l][c] == v;

  }

 if(t)
  cout << "Ok" << " - ";

 else

  cout << "Erreur" << " - ";

 return t;

}

//-------------------------------------------------------------------------------------------------
// Algorithme de base

void mul_1(void)
{

 int

  l,

  c,

  i;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

  {

   r[l][c] = 0.0;

   for(i = 0; i < N; i++)

    r[l][c] += m1[l][i] * m2[i][c];

  }

}

//-------------------------------------------------------------------------------------------------
// Algorithme de base avec variable intermédiaire

void mul_2(void)
{

 int

  l,

  c,

  i;

 TYPE s;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

  {

   s = 0.0;

   for(i = 0; i < N; i++)

    s += m1[l][i] * m2[i][c];

   r[l][c] = s;

  }

}

//-------------------------------------------------------------------------------------------------
// Algorithme de base avec initialisation

void mul_3(void)
{

 int

  l,

  c,

  i;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

  {

   r[l][c] = m1[l][0] * m2[0][c];

   for(i = 1; i < N; i++)

    r[l][c] += m1[l][i] * m2[i][c];

  }

}

//-------------------------------------------------------------------------------------------------
// Algorithme de base avec variable intermédiaire et initialisation

void mul_4(void)
{

 int

  l,

  c,

  i;

 TYPE s;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

  {

   s = m1[l][0] * m2[0][c];

   for(i = 1; i < N; i++)

    s += m1[l][i] * m2[i][c];

   r[l][c] = s;

  }

}

//-------------------------------------------------------------------------------------------------
// Maeno Toshinori

// Tokyo Institute of Technology

// N mod L = 0

#define L 30 // Taille des matrices placées en cache
#define L2 30

void mul_5(void)
{

 int

  i,

  j,

  k,

  kk,

  i2,

  kt,

  it;

 double

  t0,

  t1,

  t2,

  t3,

  s,

  t4,

  t5,

  t6,

  t7;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

   r[i][j] = 0.0;

 for(i2 = 0; i2 < N; i2 += L2)

  for(kk = 0; kk < N; kk += L)

  {

   it = i2 + L;

   kt = kk + L;

   for(j = 0; j < N; j += 4)

    for(i = i2; i < it; i += 2)

    {

     t0 = t1 = t2 = t3 = 0.0;

     t4 = t5 = t6 = t7 = 0.0;

     for(k = kk; k < kt; k++)

     {

      s = m1[i][k];

      t0 += s * m2[k][j];

      t1 += s * m2[k][j + 1];

      t2 += s * m2[k][j + 2];

      t3 += s * m2[k][j + 3];

      s = m1[i + 1][k];

      t4 += s * m2[k][j];

      t5 += s * m2[k][j + 1];

      t6 += s * m2[k][j + 2];

      t7 += s * m2[k][j + 3];

     }

     r[i][j] += t0;

     r[i][j + 1] += t1;

     r[i][j + 2] += t2;

     r[i][j + 3] += t3;

     r[i + 1][j] += t4;

     r[i + 1][j + 1] += t5;

     r[i + 1][j + 2] += t6;

     r[i + 1][j + 3] += t7;

    }

  }

}

//-------------------------------------------------------------------------------------------------
// Dan Warner

// Dept. of Mathematics, Clemson University

#define NB 40

void mul_6(void)
{

 int

  i,

  j,

  k,

  ii,

  jj,

  kk;

 double

  s00,

  s01,

  s10,

  s11;

 for(ii = 0; ii < N; ii += NB)
  for(jj = 0; jj < N; jj += NB)

  {

   for(i = ii; i < ii + NB; i++)

    for(j = jj; j < jj + NB; j++)

     r[i][j] = 0.0;

   for(kk = 0; kk < N; kk += NB)

    for(i = ii; i < ii + NB; i += 2)

     for(j = jj; j < jj + NB; j += 2)

     {

      s00 = r[i][j];

      s01 = r[i][j + 1];

      s10 = r[i + 1][j];

      s11 = r[i + 1][j + 1];

      for(k = kk; k < kk + NB; k++)

      {

       s00 += m1[i][k] * m2[k][j];

       s01 += m1[i][k] * m2[k][j + 1];

       s10 += m1[i + 1][k] * m2[k][j];

       s11 += m1[i + 1][k] * m2[k][j + 1];

      }

      r[i][j] = s00;

      r[i][j + 1] = s01;

      r[i + 1][j] = s10;

      r[i + 1][j + 1] = s11;

     }

  }

}

//-------------------------------------------------------------------------------------------------
// Inversion des boucles les plus intérieures

void mul_7(void)
{

 int

  i,

  j,

  k;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

   r[i][j] = 0.0;

 for(i = 0; i < N; i++)

  for(k = 0; k < N; k++)

   for(j = 0; j < N; j++)

    r[i][j] += m1[i][k] * m2[k][j];

}

//-------------------------------------------------------------------------------------------------
// Inversion des boucles les plus intérieures avec variable intermédiaire

void mul_8(void)
{

 int

  i,

  j,

  k;

 double

  temp;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

   r[i][j] = 0.0;

 for(i = 0; i < N; i++)

  for(k = 0; k < N; k++)

  {

   temp = m1[i][k];

   for(j = 0; j < N; j++)

    r[i][j] += temp * m2[k][j];

  }

}

//-------------------------------------------------------------------------------------------------
// Pavage de longueur step

#define min(a, b) ((a) < (b) ? (a) : (b))

void mul_9(void)
{

 int

  i,

  j,

  k,

  jj,

  kk,

  step = 8; // 4 or 8 or 16 or 32 or 64 or 96

 double

  temp;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

   r[i][j] = 0.0;

 for(kk = 0; kk < N; kk += step)

  for(jj = 0; jj < N; jj += step)

   for(i = 0; i < N; i++)

    for(k = kk; k < min(kk + step, N); k++)

    {

     temp = m1[i][k];

     for(j = jj; j < min(jj + step, N); j++)

      r[i][j] += temp * m2[k][j];

    }

}

//-------------------------------------------------------------------------------------------------
// Boucle raccourcie de 4

// N >= 4

void mul_10(void)
{

 int

  i,

  j,

  k;

 double

  temp;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

  {

   temp = 0.0;

   for(k = 0; k < N - 3; k += 4)

   {

    temp += m1[i][k] * m2[k][j];

    temp += m1[i][k + 1] * m2[k + 1][j];

    temp += m1[i][k + 2] * m2[k + 2][j];

    temp += m1[i][k + 3] * m2[k + 3][j];

   }

   for(; k < N; k++)

    temp += m1[i][k] * m2[k][j];

   r[i][j] = temp;

  }

}

//-------------------------------------------------------------------------------------------------
// Boucle raccourcie de 8

// N >= 8

void mul_11(void)
{

 int

  i,

  j,

  k;

 double

  temp;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

  {

   temp = 0.0;

   for(k = 0; k < N - 7; k += 8)

   {

    temp += m1[i][k] * m2[k][j];

    temp += m1[i][k + 1] * m2[k + 1][j];

    temp += m1[i][k + 2] * m2[k + 2][j];

    temp += m1[i][k + 3] * m2[k + 3][j];

    temp += m1[i][k + 4] * m2[k + 4][j];

    temp += m1[i][k + 5] * m2[k + 5][j];

    temp += m1[i][k + 6] * m2[k + 6][j];

    temp += m1[i][k + 7] * m2[k + 7][j];

   }

   for(; k < N; k++)

    temp += m1[i][k] * m2[k][j];

   r[i][j] = temp;

  }

}

//-------------------------------------------------------------------------------------------------
// Boucle raccourcie de 16

// N >= 16

void mul_12(void)
{

 int

  i,

  j,

  k;

 double

  temp;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

  {

   temp = 0.0;

   for(k = 0; k < N - 15; k += 16)

   {

    temp += m1[i][k] * m2[k][j];

    temp += m1[i][k + 1] * m2[k + 1][j];

    temp += m1[i][k + 2] * m2[k + 2][j];

    temp += m1[i][k + 3] * m2[k + 3][j];

    temp += m1[i][k + 4] * m2[k + 4][j];

    temp += m1[i][k + 5] * m2[k + 5][j];

    temp += m1[i][k + 6] * m2[k + 6][j];

    temp += m1[i][k + 7] * m2[k + 7][j];

    temp += m1[i][k + 8] * m2[k + 8][j];

    temp += m1[i][k + 9] * m2[k + 9][j];

    temp += m1[i][k + 10] * m2[k + 10][j];

    temp += m1[i][k + 11] * m2[k + 11][j];

    temp += m1[i][k + 12] * m2[k + 12][j];

    temp += m1[i][k + 13] * m2[k + 13][j];

    temp += m1[i][k + 14] * m2[k + 14][j];

    temp += m1[i][k + 15] * m2[k + 15][j];

   }

   for(; k < N; k++)

    temp += m1[i][k] * m2[k][j];

   r[i][j] = temp;

  }

}

//-------------------------------------------------------------------------------------------------
// Utilisation de pointeurs

// N mod 8 = 0

void mul_13(void)
{

 int

  i,

  j,

  k;

 double

  t,

  *aa,

  *bb;

 for(i = 0; i < N; i++)
  for(j = 0; j < N; j++)

  {

   t = 0;

   aa = m1[i];

   bb = &m2[0][j];

   for(k = 0; k < N / 8; k++)

   {

    t += *aa++ * bb[0];

    t += *aa++ * bb[N];

    t += *aa++ * bb[2 * N];

    t += *aa++ * bb[3 * N];

    t += *aa++ * bb[4 * N];

    t += *aa++ * bb[5 * N];

    t += *aa++ * bb[6 * N];

    t += *aa++ * bb[7 * N];

    bb += 8 * N;

   }

   r[i][j] = t;

  }

}

//-------------------------------------------------------------------------------------------------
// Vincent LESAUVAGE

// N mod 2 = 0

// Carrés de 2

void mul_14(void)
{

 int

  c,

  c2,

  l;

 double

  t0,

  t1,

  t2,

  t3;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

   r[l][c] = 0.0;

 for(l = 0; l < N; l += 2)

  for(c = 0; c < N; c += 2)

  {

   t0 = t1 = t2 = t3 = 0.0;

   for(c2 = 0; c2 < N; c2 += 2)

   {

    t0 += m1[l][c2] * m2[c2][c] + m1[l][c2 + 1] * m2[c2 + 1][c];

    t1 += m1[l][c2] * m2[c2][c + 1] + m1[l][c2 + 1] * m2[c2 + 1][c + 1];

    t2 += m1[l + 1][c2] * m2[c2][c] + m1[l + 1][c2 + 1] * m2[c2 + 1][c];

    t3 += m1[l + 1][c2] * m2[c2][c + 1] + m1[l + 1][c2 + 1] * m2[c2 + 1][c + 1];

   }

   r[l][c] = t0;

   r[l][c + 1] = t1;

   r[l + 1][c] = t2;

   r[l + 1][c + 1] = t3;

  }

}

//-------------------------------------------------------------------------------------------------
// Vincent LESAUVAGE

// N mod 3 = 0

// Carrés de 3

void mul_15(void)
{

 int

  c,

  c2,

  l;

 double

  t0,

  t1,

  t2,

  t3,

  t4,

  t5,

  t6,

  t7,

  t8;

 for(l = 0; l < N; l++)
  for(c = 0; c < N; c++)

   r[l][c] = 0.0;

 for(l = 0; l < N; l += 3)

  for(c = 0; c < N; c += 3)

  {

   t0 = t1 = t2 = 0.0;

   t3 = t4 = t5 = 0.0;

   t6 = t7 = t8 = 0.0;

   for(c2 = 0; c2 < N; c2 += 3)

   {

    t0 += m1[l][c2] * m2[c2][c] + m1[l][c2 + 1] * m2[c2 + 1][c] +

     m1[l][c2 + 2] * m2[c2 + 2][c];

    t1 += m1[l][c2] * m2[c2][c + 1] + m1[l][c2 + 1] * m2[c2 + 1][c + 1] +

     m1[l][c2 + 2] * m2[c2 + 2][c + 1];

    t2 += m1[l][c2] * m2[c2][c + 2] + m1[l][c2 + 1] * m2[c2 + 1][c + 2] +

     m1[l][c2 + 2] * m2[c2 + 2][c + 2];

 

    t3 += m1[l + 1][c2] * m2[c2][c] + m1[l + 1][c2 + 1] * m2[c2 + 1][c] +

     m1[l + 1][c2 + 2] * m2[c2 + 2][c];

    t4 += m1[l + 1][c2] * m2[c2][c + 1] + m1[l + 1][c2 + 1] * m2[c2 + 1][c + 1] +

     m1[l + 1][c2 + 2] * m2[c2 + 2][c + 1];

    t5 += m1[l + 1][c2] * m2[c2][c + 2] + m1[l + 1][c2 + 1] * m2[c2 + 1][c + 2] +

     m1[l + 1][c2 + 2] * m2[c2 + 2][c + 2];

    t6 += m1[l + 2][c2] * m2[c2][c] + m1[l + 2][c2 + 1] * m2[c2 + 1][c] +
     m1[l + 2][c2 + 2] * m2[c2 + 2][c];

    t7 += m1[l + 2][c2] * m2[c2][c + 1] + m1[l + 2][c2 + 1] * m2[c2 + 1][c + 1] +

     m1[l + 2][c2 + 2] * m2[c2 + 2][c + 1];

    t8 += m1[l + 2][c2] * m2[c2][c + 2] + m1[l + 2][c2 + 1] * m2[c2 + 1][c + 2] +

     m1[l + 2][c2 + 2] * m2[c2 + 2][c + 2];

   }

   r[l][c] = t0;

   r[l][c + 1] = t1;

   r[l][c + 2] = t2;

   r[l + 1][c] = t3;

   r[l + 1][c + 1] = t4;

   r[l + 1][c + 2] = t5;

   r[l + 2][c] = t6;

   r[l + 2][c + 1] = t7;

   r[l + 2][c + 2] = t8;

  }

}

//-------------------------------------------------------------------------------------------------
// Vincent LESAUVAGE

// a (NxM), b (MxP), p (NxP)

// N, M, P mod 2 = 0

// Carrés de 2

void mul_16(void)
{

 int

  c,

  c2,

  l;

 double

  t0,

  t1,

  t2,

  t3;

 for(l = 0; l < N; l++)
  for(c = 0; c < P; c++)

   p[l][c] = 0.0;

 for(l = 0; l < N; l += 2)

  for(c = 0; c < P; c += 2)

  {

   t0 = t1 = t2 = t3 = 0.0;

   for(c2 = 0; c2 < M; c2 += 2)

   {

    t0 += a[l][c2] * b[c2][c] + a[l][c2 + 1] * b[c2 + 1][c];

    t1 += a[l][c2] * b[c2][c + 1] + a[l][c2 + 1] * b[c2 + 1][c + 1];

    t2 += a[l + 1][c2] * b[c2][c] + a[l + 1][c2 + 1] * b[c2 + 1][c];

    t3 += a[l + 1][c2] * b[c2][c + 1] + a[l + 1][c2 + 1] * b[c2 + 1][c + 1];

   }

   p[l][c] = t0;

   p[l][c + 1] = t1;

   p[l + 1][c] = t2;

   p[l + 1][c + 1] = t3;

  }

}