L’opération essentielle en algèbre linéaire est sans doute la succession d’une multiplication
et d’une addition (ou accumulation à un résultat temporaire) : y ← ax+y. Souvent appelée
AXPY, cette opération peut être vue comme atomique, surtout depuis son introduction en
vir-gule flottante dans les processeurs sous le nom defused-mac. Ainsi, les arithmétiques de corps
premiers définissent aussi cette opération, ce qui permet de n’appliquer qu’une réduction
mo-dulaire pour deux opérations arithmétiques.
Le produit scalaire consiste ensuite à enchaîner ces opérations sur les éléments de deux
vec-teurs, ce qui permet en particulier d’utiliser les structures depipelinedes architectures dans le
cas des calculs flottants. En revanche, sur des corps finis, la réduction modulaire après chaque
AXPYest pénalisante (ajout d’opérations et éventuellement de branchements conditionnels) et
empêche une mise enpipelineefficace des calculs.
De ce constat est née l’idée de différer la réduction modulaire autant que possible. En effet,
pour toutes les implémentations décrites précédemment, sauf celle des logarithmes de Zech,
les éléments sont plongés canoniquement dans Zet peuvent donc être maniés par les unités
arithmétiques machine. Une réduction modulaire finale permet ensuite de retrouver le résultat
dans le corps fini. La représentation de Zpar les mots machine est bien sûr limitée à un
in-tervalle borné. L’approche différée n’est donc valide que lorsque les résultats restent dans cet
intervalle.
Par exemple si on utilise une représentation positive sur des mots deγ bits avec le modulo
p, on peut effectuerλaccumulations sans réduction modulaire si
λ(p−1)
2<2
γ. (1.1)
Si la représentation est centrée, (i.e. −
p−21≤ x ≤
p−21pour la représentation d’un élémentx
du corps premier impairZ
p), l’équation 1.1 devient :
λ
p−1
2
2<2
γ−1(1.2)
ce qui amélioreλd’un facteur2. A noter qu’un bit est pris à la mantisse pour exprimer le signe
(d’où leγ−1).
Ainsi, le surcoût des réductions modulaires peut être amorti puisque seulement
n λréduc-tions sont nécessaires pour un produit scalaire de dimensionn.
Par ailleurs, on note que la représentation centrée est mieux adaptée aux calculs avec
réduc-tion modulaire différée. Dans la mesure où on a le choix d’utiliser cette représentaréduc-tion, il faut
la préférer. Cependant, de nombreuse implémentations existantes pour les corps finis utilisent
des représentations positives. Pour cette raison, nous déclinons par la suite chaque résultat
concernant les réductions modulaires différées pour les représentations positives et centrées.
LE PRODUIT MATRICIEL
Nous présentons ici des travaux sur le produit matriciel que nous avons initiés dans [91],
publié dans [34] et prolongés depuis.
2.1 Par l’algorithme classique
Nous considérons l’opération C ← A× B où la matrice A a pour dimensions m ×k,
B, k ×n et C, m ×n. Par algorithme classique, nous désignons la méthode qui consiste à
cacluler chacun desm×ncoefficients du résultat comme un produit scalaire de dimensionk.
Les opérations arithmétiques sont donc l’addition et la multiplication sur le corps fini. Nous
étudions ici comment les ordonnancer de la manière la plus efficace.
2.1.1 Réduction modulaire différée
Le produit matriciel étant vu comme un ensemble de produits scalaires, on peut donc lui
appliquer la remarque de la partie 1.2 : la réduction modulaire peut être différée. Soit λ le
nombre maximal de AXPY pouvant être effectués sans réduction modulaire. Nous
distingue-rons essentiellement deux cas :
– celui des représentations positives sur des mots deγ bits non signés, pour lesquelles λ
vérifie
λ(p−1)
2<2
γ≤(λ+ 1)(p−1)
2. (2.1)
– celui des représentations centrées sur des mots deγ bits signés, pour lesquellesλvérifie
λ
p−1
2
2<2
γ−1≤(1 +λ)
p−1
2
2. (2.2)
Cette contrainte induit un découpage en blocs des matrices à multiplier :Aest découpée en
k/λblocs de dimensionm×λetB enk/λblocs de dimensionλ×n(sauf les derniers blocs
deAetB qui sont de dimension plus petite).
Ainsi, l’algorithme consiste maintenant à effectuer les produits par blocs par une
arithmé-tique de Z, en effectuant les réductions modulaires entre chaque opération de blocs. Cette
organisation laisse maintenant entrevoir la possibilité d’utiliser les routines numériques
spé-cialisées, pour effectuer les opérations de blocs. C’est ce que nous allons maintenant étudier.
2.1.2 Utilisation de l’arithmétique flottante
Une approche naïve pour le produit matrice-vecteur et la multiplication matricielle serait de
les considérer comme respectivementnoun
2produits scalaires. De la sorte l’efficacité serait
celle du produit scalaire, traitée dans [31] : en général autour d’une opération de corps pour
deux cycles d’horloge.
Or des efforts considérables ont été menés pour améliorer ces opérations linéaires en tirant
parti de la structure hiérarchique de la mémoire des ordinateurs actuels ainsi que des unités
arithmétiques spécialisées [118]. Dans la plupart des architectures des ordinateurs modernes,
un accès à la mémoire vive est plus de cent fois plus coûteux qu’une opération arithmétique.
Pour contourner ce ralentissement, la mémoire est structurée en deux ou trois niveaux de
mé-moire cache, jouant le rôle de tampon pour réduire le nombre d’accès à la mémé-moire vive et
réutiliser au maximum les données chargées. Cette technique n’est valable que si l’algorithme
permet la réutilisation de certaines données. C’est la principale raison pour laquelle le produit
matriciel est particulièrement bien adapté à ce type d’optimisation : c’est la première opération
basique en algèbre linéaire dont la complexité arithmétiqueO(n
3)est d’un ordre de grandeur
supérieur à la complexité en mémoireO(n
2).
Ces considérations ont mené les numériciens à l’élaboration des BLAS [83, 28, 27], dont
l’efficacité est principalement basée sur un noyau optimisé pour le produit matriciel. L’un de
ses principes constitutifs est d’effectuer les produits matriciels par blocs de petite dimension,
de sorte que les arguments pour un produit de blocs tiennent dans la mémoire cache, limitant
ainsi les surcoûts d’accès mémoire. Initialement, ces routines étaient fournies par le
construc-teur d’une architecture donnée. Mais les récents travaux de [118] ont permis le développement
de BLAS génériques s’adaptant aux spécificités de la plupart des architectures existantes grâce
à un système d’optimisations basées sur des expérimentations lors de l’installation. L’efficacité
de telles routines est sans comparaison : par exemple la puissance de crête du produit
matri-ciel sur un Pentium 4 cadencé à 3,4 Ghz est de 5,276milliards d’opérations par seconde, ce
qui correspond à 1,55opérations arithmétiques par cycle d’horloge. Cette efficacité provient
d’une utilisation pertinente des niveaux de cache, des structures depipelineet du parallélisme
interne à ce type de processeur.
Il est donc tout naturel d’utiliser ces routines pour effectuer les produits matriciels surZdes
blocs décrits dans la partie 2.1.1. Pour ce faire on doit pouvoir convertir les éléments du corps
fini vers leur image dans Zreprésentée sur undouble. A l’inverse on doit aussi disposer du
mécanisme réciproque de conversion d’un entier représenté sur undoublevers un élément
du corps fini, impliquant une réduction modulaire. Ces conversions sont toujours réalisables,
mais elles demandent de dupliquer les blocs de matrices dans le cas d’une implémentation
quelconque. En revanche, l’avantage de l’implémentationModular<double>tient dans le
fait que les éléments sont directement représentés sur desdouble, et les BLAS peuvent donc
les utiliser sans recopie. Après le calcul sur Z, une simple réduction modulaire suffit pour
retrouver le résultat sur le corps fini.
Dans le document
Algèbre linéaire exacte efficace : le calcul du polynôme caractéristique
(Page 38-41)