• Aucun résultat trouvé

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. −

p21

≤ x ≤

p21

pour 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

2

produits 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.