3 votes

Comparaison des performances d'Eigen::Tensor et Eigen::Matrix

Je voudrais remplacer une séquence de matrices dans mon code par un seul 3-D Eigen::Tensor. Dans cette optique, j'essaie de comparer les performances de Tensor et de Matrix.

La fonction "tensorContractTest" ci-dessous effectue une contraction d'un tenseur de rang 3 (n,n,n) avec un tenseur de rang 1 de taille n (n = 500). Cette contraction calcule n**2 produits scalaires, donc en termes du nombre d'opérations, c'est équivalent à la multiplication de deux matrices (n,n) (fonction "matrixProductTest" ci-dessous).

En exécutant sur Visual Studio 2013, la fonction "tensorContractTest" s'exécute environ 40 fois plus lentement que "matrixProductTest". Probablement, je fais une erreur quelque part. Votre aide est appréciée.

#include 
using namespace Eigen;

// Contrat un tenseur 3D (n x n x n) avec un tenseur 1D (n).
// En nombre d'opérations, c'est équivalent à la multiplication
// de deux matrices (n, n) (matrixProdTest).
Tensor  tensorContractTest(int n)
{
  Tensor a(n, n, n);     a.setConstant(1.);  
  Tensor b(n);           b.setConstant(1.);
  auto indexPair            = array, 1>{IndexPair(2,0)}; 
  Tensor result  = a.contract(b, indexPair); 
  return result;
}

MatrixXd  matrixProductTest(int n)
{ 
  MatrixXd a = MatrixXd::Ones(n, n), result = a * a;
  return result;
}

1voto

Parce que la contraction de tenseur n'est pas la même que la multiplication de matrices.

Il existe des algorithmes spécialisés pour la multiplication de matrices tels que l'algorithme de Strassen qui réduit le nombre total d'opérations. De plus, les bibliothèques de matrices ont été hautement optimisées au fil des ans, donc elles sont généralement spécialisées pour utiliser des instructions vectorisées (SIMD ou AVX) en fonction de la plate-forme (Intel, AMD, ARM). Pour les matrices de petites tailles ou avec des motifs épars, le gain de vitesse est énorme par rapport au code non spécialisé.

En revanche, les bibliothèques de tenseurs ont tendance à être moins optimisées en comparaison. Donc si vous pouvez convertir vos mathématiques de tenseurs en algèbre matricielle, il y a de fortes chances pour que la vitesse augmente.

1voto

ggael Points 18968

Même si le nombre d'opérations en virgule flottante est du même ordre, les schémas d'accès à la mémoire sont complètement différents et donc les deux opérations ne sont pas du tout comparables. En général, l'opération matrice-matrice sera toujours plus rapide (en termes de FLOPS) que l'opération matrice-vecteur ou vecteur-vecteur car la première permet une meilleure utilisation du cache et donc une utilisation presque optimale de l'ALU du CPU. Dans votre cas, d'un côté, vous devez lire un tenseur n^3 par rapport à deux matrices n^2, donc les empreintes mémoire ne sont pas du tout comparables.

En interne, Tensor::contract fait appel aux noyaux de produit matriciel d'Eigen lorsque c'est possible, donc les performances devraient être équivalentes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X