FR 2986343 A1 20130802 FR 1200247 A 20120127 DESCRIPTION La présente invention concerne un procédé de pré-compilation, un procédé de compilation, un programme d'ordinateur et un système informatique. Dans la description et les revendications qui vont suivre, la terminologie suivante sera employée. Une ligne de code, appelée par la suite simplement « ligne », est combinaison de fonctions et/ou variables et/ou constantes destinée à être évaluée selon des règles de priorité d'évaluation des fonctions. Une fonction est un ensemble d'instructions qui, lors de son exécution par un processeur, réalisent une ou plusieurs actions. Une fonction peut attendre aucun, un ou plusieurs arguments et retourner aucun ou un résultat. Une variable est un objet informatique destiné à contenir des données. Une variable comporte un nom et est destinée à contenir un certain type de donnée. Ainsi, une variable de type matrice est une variable destinée à contenir une matrice. Dans la suite, une variable sera simplement désignée par son type, de sorte qu'une « matrice » signifiera « une variable de type matrice ». Un bloc de code est l'ensemble d'une ou plusieurs lignes successives 20 ou séparées. Simplifier du code signifie réduire le nombre de fonctions et/ou de variables présentes dans le code, sans changer le résultat final de l'exécution du code. Affecter une matrice à une variable de type matrice signifie enregistrer 25 la matrice dans la variable. Allouer une variable signifie définir un espace mémoire destiné à contenir les données de la variable. Une opération matricielle est une fonction ayant au moins une matrice comme argument et/ou retournant un résultat de type matrice. Une expression matricielle est une combinaison finie et syntaxiquement correcte de symboles, dont une partie représente des opérations matricielles, et dont une autre partie représente des matrices. Un calcul matriciel correspond à une seule opération ou plusieurs 5 opérations matricielles combinées sur une seule ligne ou réparties sur plusieurs lignes. La compilation est l'opération transformant un code source écrit dans un langage de programmation en une succession d'instructions spécifiques à un processeur, appelé code machine. La qualité de la compilation se mesure 10 en fonction de la taille du code machine obtenu (la plus petite possible pour économiser de la mémoire) et/ou de la vitesse d'exécution du code sur le processeur ciblé (la plus rapide possible pour traiter le plus de tâches possible). Le langage de programmation peut être généraliste comme le 15 langage C ou C++, c'est-à-dire qu'il permet de décrire de nombreux types de traitement. Mais dans beaucoup de domaines, d'autres langages plus spécialisés sont préférés, car ils permettent une description plus concise et plus naturelle. En traitement du signal, le langage Matlab (marque déposée) est souvent utilisé. Il existe en outre des librairies C++ qui fournissent une 20 syntaxe proche de celle de Matlab. Dans le langage C++, une matrice est représentée sous la forme d'un tableau. Il existe par ailleurs des librairies fournissant un type de donnée destiné à représenter une matrice. 25 L'invention a pour but de permettre d'optimiser un programme utilisant des matrices. A cet effet, il est proposé un procédé de pré-compilation d'un code source écrit dans un langage informatique et comportant des lignes de code, caractérisé en ce qu'il comporte : - la détermination, dans le code source, de 30 la présence d'un au plusieurs calculs matriciels sur une ou plusieurs matrices, appelées matrices d'entrée, dont le résultat est affecté à une matrice, appelée matrice de résultat ; - la modification du code source en fonction du ou des calculs matriciels dont la présence a été déterminée. De façon optionnelle, la modification du code source comporte : - la détermination, pour chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes de calcul de taille, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur, calculent les dimensions de la matrice de résultat à partir d'au moins une des dimensions d'au moins une matrice d'entrée. En effet, en C, la taille d'une matrice est en général indiquée lors de la déclaration d'un matrice. Par exemple, la ligne int M [5][5]; déclare une matrice M d'entiers présentant cinq lignes et cinq colonnes. Dans le cas d'une librairie C++ définissant un type de données « matrice » sous la forme d'une classe, il est en revanche connu que ce type de donnée ne nécessite pas d'indiquer la taille de la matrice lors de sa déclaration. Cependant, dans un cas comme dans l'autre, lors de la compilation, le compilateur, lorsqu'il rencontre une déclaration de matrice dans le code source, introduit dans le code machine un appel à une fonction d'initialisation, appelée constructeur et définie dans la librairie en même temps que le type de donnée matrice. Le constructeur comporte des lignes pour calculer la taille de la matrice afin de lui allouer un espace mémoire suffisant. Cette manière de compiler présente comme problème que chaque déclaration d'une matrice va entraîner l'apparition dans le code machine d'un appel au constructeur, qui sera donc exécuté à chaque fois lors de l'exécution du programme compilé (le code machine). En conséquence, les lignes pour calculer la taille de la matrice seront également exécutées pour chaque déclaration de matrice, sans qu'il ne soit possible d'exercer un quelconque contrôle sur l'intérêt de ces lignes dans le contexte du programme compilé. Au contraire, dans ce mode de réalisation de l'invention, le calcul de taille apparaît dans le code source, avant qu'il ne soit compilé, c'est-à-dire traduit en code machine. Ainsi, il est possible d'effectuer toutes sortes de traitement sur ces lignes avant la compilation, en particulier des traitements d'optimisation de code. De façon optionnelle également, la modification du code source comporte : - la détermination, pour chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes d'allocation, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur, allouent un espace mémoire à la matrice de résultat à partir des dimensions de la matrice de résultat qui ont été calculées. De façon optionnelle également, le procédé comporte en outre : - la 10 simplification des lignes déterminées pour diminuer le nombre de fonctions et/ou de variables présentes dans ces lignes ; les lignes simplifiées étant insérées dans le code source. De façon optionnelle également, la simplification des lignes comporte : - la détermination, dans les lignes, de l'affectation d'une même 15 expression à deux variables différentes ; - la suppression de l'affectation d'une première des deux variables et le remplacement, dans les lignes, de la première variable par la seconde des deux variables. De façon optionnelle également, la simplification des lignes comporte : - la détermination de la présence, dans la ou les lignes de calcul 20 de taille, d'une combinaison d'appels de fonction d'au moins une dimension d'au moins une matrice d'entrée ; - la simplification de la combinaison d'appels de fonction à partir de règles prédéterminées de simplification de combinaisons d'appels de fonction. De façon optionnelle également, la modification du code source 25 comporte : - l'insertion, dans le code source, à la place de chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes de commande, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur, commandent un dispositif électronique, différent du processeur, spécialisé pour réaliser le 30 calcul matriciel, afin que ce dispositif électronique spécialisé réalise le calcul matriciel. De façon optionnelle également, le ou les calculs matriciels dont la présence est déterminée appartiennent chacun à une liste prédéterminée de calculs matriciels, et dans lequel le dispositif électronique est spécialisé pour réaliser chacun des calculs matriciels de la liste prédéterminée. De façon optionnelle également, les calculs matriciels de la liste prédéterminée sont des calculs matriciels conformes à une expression prédéterminée. De façon optionnelle également, la ou les lignes de commande sont destinées à être compilées en instructions qui, lorsqu'exécutées par un 10 processeur, transmettent au dispositif électronique spécialisé les matrices d'entrée et les opérations matricielles du calcul matriciel. De façon optionnelle également, l'allocation d'un espace mémoire pour la matrice de résultat est réalisée dans une mémoire du dispositif électronique spécialisé, ce dernier étant destiné à écrire le résultat du calcul 15 matriciel dans l'espace mémoire alloué. Il est en outre proposé un procédé de compilation comportant, d'une part, un procédé de pré-compilation selon l'invention, et, d'autre part : - la compilation du code source modifié au cours du procédé de pré-compilation en code machine destiné à être exécuté par un système informatique, appelé 20 système informatique cible. Il est en outre proposé un programme d'ordinateur comportant des instructions qui, lorsqu'exécutés par un processeur d'un système informatique, entraînent la mise en oeuvre d'un procédé de pré-compilation selon l'invention, ou bien d'un procédé de compilation selon l'invention. 25 Il est en outre proposé un système informatique comportant : - un processeur ; - une mémoire vive ; et - une mémoire de masse dans laquelle est enregistré un programme d'ordinateur selon l'invention destiné à être chargé en mémoire vive pour être exécuté par le processeur. Un exemple de mise en oeuvre de l'invention va à présent être décrit 30 en référence aux figures suivantes : - la figure 1 est une vue schématique d'un système informatique de compilation et d'un système informatique cible selon l'invention, - la figure 2, scindée en figures 2A et 2B, est un schéma-blocs d'un procédé de compilation selon l'invention mis en oeuvre par le système informatique de la figure 1. En référence à la figure 1, un exemple de système informatique de 5 compilation 100 selon l'invention va être décrit. Le système informatique 100 comporte tout d'abord un processeur 102. Le système informatique 100 comporte en outre une mémoire de masse 104. La mémoire de masse 104 est de préférence non volatile. Il 10 s'agit par exemple d'un disque dur, d'une clé USB, d'un disque compact (CD ou DVD), etc. Le système informatique 100 comporte en outre de la mémoire vive 106. La mémoire vive 106 est de préférence de la mémoire volatile. Il s'agit par exemple de mémoire RAM (de l'anglais « Random Access Memory »). 15 Un code source 108 est enregistré dans la mémoire de masse 104. Le code source 108 comporte des lignes de code écrites dans un langage informatique prédéterminé, c'est-à-dire respectant la syntaxe de ce langage informatique. Dans l'exemple décrit, le langage informatique est le langage C++. 20 Dans l'exemple décrit, le code source 108 est le suivant : void example_compilation(int N) { Array A = fl(); Array B = f2(); Array C = conj(A) + B; 25 Array D = A - B; Array E = C > D; } Un programme informatique de compilation, appelé dans la suite compilateur 110, est enregistré dans la mémoire de masse 104 et destiné à être chargé dans la mémoire vive 106 afin d'être exécuté par le processeur 30 102. Le compilateur 110 est conçu pour traduire le code source 108 en code machine destiné à être exécuté par un processeur d'un système informatique, appelé système informatique cible 112. Dans l'exemple décrit, le système informatique cible 112 est différent du système informatique 100. En variante, le système informatique cible pourrait être le système informatique 100. Le système informatique cible 112 comporte en particulier 5 un processeur 114 (par exemple, un micro-contôleur de séquencement) pour exécuter le code machine et un dispositif électronique 116 (par exemple un coprocesseur ou un accélérateur) spécialisé pour réaliser des calculs matriciels, comme cela sera expliqué par la suite. Par ailleurs, le dispositif électronique spécialisé 116 comporte une mémoire 118, dans laquelle le 10 dispositif électronique simplifié 116 est destiné à écrire le résultat du calcul matriciel. Dans l'exemple décrit, le dispositif électronique spécialisé 116 est destiné à réaliser chacun d'une pluralité de calculs matriciels d'une liste prédéterminée, noté (L). 15 Dans l'exemple décrit, le dispositif électronique spécialisé 116 est destiné à réaliser les calculs matriciels qui sont conformes à une expression prédéterminée d'opérations matricielles, notée (Exp). Une expression est une combinaison bien formée (c'est-à-dire respectant les règles mathématiques), et de préférence finie, de symboles. Certains symboles, 20 appelés symboles de matrice, représentent des matrices, appelées matrices d'entrée de l'expression, à partir desquelles l'expression est évaluée, tandis que d'autres symboles, appelés symboles d'opération, représentent chacun une opération sur une ou plusieurs matrices d'entrée. De préférence, chaque symbole représente une opération prise dans une liste prédéterminée. 25 Dans l'exemple décrit, l'expression prédéterminée (Exp) est : (Exp) : opl( op2( op3(A), op4(B) ) ) où opl, op2, op3 et op4 sont les symboles d'opération, et A et B sont les matrices d'entrée. Dans l'exemple décrit, la liste d'opérations de chaque symbole 30 d'opération comporte une ou plusieurs des opérations : addition, opposé, conjugaison, inverse, multiplication, transposition, etc. Un calcul matriciel conforme à l'expression prédéterminée précédente est par exemple : inverse( -A + conjuguée(B) ) Dans cette exemple, le premier symbole d'opération opi correspond à l'opération inverse, le deuxième symbole d'opération op2 correspond à l'opération d'addition, le troisième symbole d'opération op3 correspond à l'opération d'opposée et le quatrième symbole d'opération op4 correspond à l'opération de conjugaison. Le compilateur 110 comporte un pré-compilateur 120 et en un 10 compilateur principal 122. Le pré-compilateur 120 est conçu pour modifier le code source afin de fournir un code source modifié, respectant toujours la syntaxe du langage de programmation (le langage C++ dans l'exemple décrit). Les modifications apportées par le pré-compilateur 112 seront détaillées lors de la description 15 de la figure 2. Le compilateur principal 122 est conçu pour traduire le code source modifié en code machine destiné à être exécuté par le processeur 114 du système informatique cible 112. Dans l'exemple décrit, le compilateur principal 122 est le compilateur MB C++. 20 Une librairie informatique 124 est également enregistrée dans la mémoire de masse 104. La librairie informatique 124 comporte tout d'abord une définition d'une structure de donnée appelée « matrice », et indiquée dans le code source par le terme « array ». Une matrice est conçue pour regrouper un 25 certain nombre de données d'un type identique (de préférence, au moins deux données), organisées en colonnes et lignes. Par exemple, une matrice peut regrouper des nombres complexes. La définition est utilisée par le compilateur principal 122 pour traduire les matrices apparaissant dans le code source, et en particulier les déclarations de matrice, en code machine 30 correspondant. Dans l'exemple décrit, la définition de la structure de données « matrice » est conçue de sorte que le code machine généré par le compilateur principal 122 lorsque ce dernier rencontre une déclaration d'une matrice, ne comporte pas d'instruction pour allouer de la mémoire vive à la matrice, c'est-à-dire qu'il ne comporte pas d'instruction pour réserver de l'espace mémoire destiné à contenir les données de la matrice. L'allocation en mémoire sera réalisée par un autre moyen qui sera détaillé plus loin. La définition définit en outre une opération d'affectation pour les matrices, permettant d'affecter des données de type matrice à une matrice. Dans l'exemple décrit, l'opération usuelle « = » du C++ est adaptée pour permettre cette affectation. La librairie 124 comporte en outre du code machine exécutable sur le système informatique cible des fonctions détaillées ci-dessous. int max_sz (int_1, int_2) Il s'agit d'une fonction nommée max_sz qui attend deux entier, int_1 et int_2, comme arguments, et qui retourne un résultat de type entier. Cette 15 fonction est conçue pour, lors de son exécution, retourner comme résultat l'argument le plus grand. void ra_init_size (array_1, int_1, int 2) Il s'agit d'une fonction nommée ra_init_size qui attend une matrice, array_1, et deux entiers , int_1 et int_2, comme arguments, et qui ne 20 retourne aucun résultat. Cette fonction est conçue pour, lors de son exécution, allouer un espace mémoire, dans la mémoire 118 du système informatique cible 112, à la matrice passée en argument, avec comme taille, c'est-à-dire comme nombre de lignes et de colonne, respectivement les deuxième et troisième arguments. 25 void ra array_prim core(array_l, int_1, int_2, int_3, array_2, int_4, array_3) Il s'agit une fonction nommée ra_array_prim_core qui est destinée à être compilée en instructions qui, lorsqu'exécutées par le processeur 114 du système informatique cible 116, commandent le dispositif électronique 30 spécialisé 116, afin que ce dernier réalise un des calculs matriciels. Dans l'exemple décrit, ce sont les arguments passés à la fonction qui indiquent à cette dernière le calcul matriciel à réaliser. Ainsi, dans l'exemple décrit, la fonction ra_array_prim_core attend, comme arguments, des matrices correspondant aux matrices d'entrée de l'expression prédéterminée. Dans l'exemple décrit, la fonction ra_array_prim_core attend en 5 outre comme arguments, pour chaque symbole d'opération apparaissant dans l'expression prédéterminée, une variable indiquant à quelle opération de la liste associée le symbole d'opération correspond. Ces arguments seront appelés par la suite les « identifiants d'opération » de la fonction ra array_prim core. 10 La fonction ra_array_prim_core attend en outre comme argument une autre matrice, dans laquelle le résultat du calcul matriciel est destiné à être enregistré. Cette matrice sera appelée par la suite « matrice de résultat ». Ainsi, dans l'exemple décrit, la fonction ra_array_prim_core attend 15 trois matrices, nommées array_1, array_2 et array_3, comme arguments. La variable array_1 contient la matrice de résultat. Les variables array_2 et array_3 contiennent les matrices d'entrée. La fonction ra_array_prim_core attend en outre quatre entiers, nommées int_l, int_2, int_3 et int_4. Ces variables contiennent les identifiants d'opération des quatre opérations du 20 calcul à réaliser. Par ailleurs, la fonction ra_array_prim_core est écrite pour considérer une matrice ne contenant qu'une seule donnée (matrice avec une seule ligne et une seule colonne) comme une matrice de taille adaptée à l'opération matricielle réalisée sur cette matrice, tous les emplacements de la 25 matrice contenant ce même nombre. Ainsi, l'opération matricielle A + [1] , où [1] est une matrice ne contenant que le nombre 1, sera considérée par la fonction ra_array_prim_core comme l'addition de la matrice A avec une matrice de taille identique dont chacun des emplacements contient le nombre 1, de sorte que le calcul matriciel précédent revient à ajouter le nombre 1 à 30 tous les éléments de la matrice A. Dans l'exemple décrit, la fonction ra_array_prim_core est destinée à être compilée en instructions qui, lorsqu'exécutées par le processeur 114, transmettent au dispositif électronique spécialisé 116 les matrices d'entrée et les opérations matricielles du calcul matriciel, afin que le dispositif électronique spécialisé 116 réalise le calcul matriciel. En référence à la figure 2, un exemple de procédé de compilation 200 5 selon l'invention, mis en oeuvre par le système informatique 100 de la figure 1, va être décrit. Au cours d'une étape 202, le compilateur 110 est chargé en mémoire vive 106 et exécuté par le processeur 102. Dans la suite, lorsqu'il sera écrit que le compilateur 110 réalise une 10 certaine action, cela signifiera que le processeur 102, exécutant les instructions du compilateur 110, réalise cette action. Au cours d'une étape 204, le pré-compilateur 112 recherche les lignes comportant une combinaison de plusieurs opérations matricielles. Dans l'exemple décrit, le pré-compilateur trouve la ligne indiquée en gras : 15 void example_compilation(int N) Array C = conj(A) + B; Array D = A - B; Array E = C > D; } Au cours d'une étape 206, pour chaque ligne trouvée à l'étape 204, le 20 pré-compilateur 112 scinde la combinaison d'opérations matricielles sur plusieurs lignes. À cet effet, le pré-compilateur 112 remplace la ligne trouvée par autant de lignes de remplacement que d'opérations matricielles dans la ligne trouvée. Chaque ligne de remplacement comporte, d'une part, l'une respective des opérations matricielles, et d'autre part, une déclaration d'une 25 matrice et une affectation du résultat de l'opération matricielle à la matrice. Dans l'exemple décrit, le code source à l'issue de l'étape 206 est donc le suivant, les lignes modifiées ou ajoutées apparaissant en gras : void example_compilation(int N) { Array A = fl(); 30 Array B = f2(); Array var_op_750 = conj(A); Array C = var_op_750 + B; Array D = A - B; Array E = C > D; } Au cours d'une étape 208, le pré-compilateur recherche les lignes comportant une déclaration d'une matrice suivie, sur la même ligne, d'une affectation d'une valeur de type matrice à la matrice, par exemple l'affectation du résultat d'une opération matricielle à la matrice. Dans l'exemple décrit, le compilateur trouve les lignes indiquées en gras : void example_compilation(int N) Array A = f1(); Array B = f2(); Array var_op_750 = conj(A); Array C = var_op_750 + B; Array D = A - B; Array E = C > D; } Au cours d'une étape 210, le pré-compilateur 112 scinde chaque ligne trouvée à l'étape 208 en une ligne comportant uniquement la déclaration de la matrice, et une ligne comportant uniquement l'affectation de la valeur à la matrice. Dans l'exemple décrit, les lignes modifiées ou ajoutées sont indiquées 20 en gras : void example_compilation(int N) Array A; A = f1(); Array B; 25 B = f2(); Array var_op_750; var_op_750 = conj(A); Array C; C = var_op_750 + B; Array D; D = A - B; Array E; E = C > D; ) Dans la suite, l'affectation à une matrice du résultat d'une opération matricielle dont aucun argument n'est lui-même le résultat d'une opération matricielle sera appelée une « opération matricielle élémentaire ». Les instructions va r_op_750 = conj(A) et D = A - B sont par exemple des opérations matricielles élémentaires, mais pas les instructions 10 A = f1() et B = f20. Au cours d'une étape 212, le pré-compilateur 112 détermine, dans le code source, la présence d'un ou plusieurs calculs matriciels sur une ou plusieurs matrices d'entrée, et dont le résultat est affecté à une matrice de résultat. 15 Dans l'exemple décrit, le ou les calculs matriciels sont repérés pour la raison qu'ils appartiennent chacun à la liste prédéterminée (L) de calculs matriciels. Dans l'exemple décrit, les calculs matriciels de la liste prédéterminée (L) sont ceux qui sont conformes à l'expression prédéterminée (Exp). 20 Dans l'exemple décrit, puisqu'à l'issue de l'étape 210, le code source ne comporte que des opérations matricielles élémentaires, chaque calcul matriciel s'étend sur une ou plusieurs lignes, appelées lignes de calcul matriciel. L'ensemble de cette ou de ces lignes de calcul matriciel est appelé un bloc de calcul matriciel. Ainsi, chaque bloc de calcul matriciel regroupe 25 une ou plusieurs lignes écrites pour réaliser un calcul matriciel sur une ou plusieurs matrices d'entrée et pour affecter le résultat du calcul matriciel dans une matrice de résultat. Dans l'exemple décrit, le pré-compilateur 112 détermine donc trois blocs de calcul matriciel : un premier bloc de calcul matriciel comportant les 30 lignes va r_op_750 = conj(A) et C = va r_op_750 + B (réalisant le calcul matriciel « conj(A) + B »), un deuxième bloc de calcul matriciel comportant la ligne D = A - B (réalisant le calcul matriciel « A-B »), et un troisième bloc de calcul matriciel comportant la ligne E = C > D (réalisant le calcul matriciel « C > D »). Comme cela va être expliqué, le pré-compilateur 112 va modifier le 5 code source en fonction du ou des calculs matriciels dont la présence a été déterminée. Au cours d'une étape 214, pour chaque bloc de calcul matriciel, le pré-compilateur 112 insère des lignes dans le code source à la place de la ou des lignes de calcul matriciel du bloc de calcul matriciel. 10 L'étape 214 comporte les étapes 216 à 224 suivantes. Au cours d'une étape 216, le pré-compilateur 112 détermine et insère, dans le code source, pour chaque calcul matriciel dont la présence a été déterminée, une ou plusieurs ligne de code, appelées lignes de calcul de taille, destinées à être compilées en instructions qui, lorsqu'exécutées par le 15 processeur 114, calculent les dimensions de la matrice de résultat à partir d'au moins une des dimensions d'au moins une matrice d'entrée. L'étape 216 comporte les étapes 218 à 220 suivantes. Au cours d'une étape 218, pour chaque calcul matriciel, le pré-compilateur 112 identifie les matrices d'entrée et les opérations matricielles 20 qui composent le calcul matriciel. Ainsi, par exemple, pour le calcul matriciel « conj(A) + B », le pré-compilateur 112 identifie les matrices A et B comme les matrices d'entrée de l'expression matricielle et les opérations d'addition, de conjugaison et d'identité comme les opérations matricielles du calcul matriciel. 25 Au cours d'une étape 220, pour chaque calcul matriciel, le pré- compilateur 112 détermine, à partir des opérations matricielles identifiées à l'étape 218, une ou plusieurs fonctions, appelées fonctions de calcul de taille, ces fonctions étant écrites pour calculer les dimensions de la matrice de résultat à partir d'au moins une dimension d'une des matrices d'entrée. 30 Dans l'exemple décrit, pour le calcul matriciel « conj(A) + B », le pré- compilateur 112 détermine que le nombre de colonnes de la matrice de résultat C est égal au plus grand parmi le nombre de colonnes de la matrice d'entrée A et le nombre de colonnes de la matrice d'entrée B (car les matrices A et B peuvent être des matrices avec un seul élément, comme cela a été expliqué précédemment), et que le nombre de lignes de la matrice de résultat C est égal au plus grand parmi le nombre de lignes de la matrice d'entrée A et le nombre de lignes de la matrice d'entrée B. Ainsi, dans l'exemple décrit, le pré-compilateur 112 détermine la fonction max_sz(A.p_nr, B.p_nr) pour calculer le nombre de lignes de la matrice de résultat, et la fonction max_sz(A.p_nc, B.p_nc) pour calculer le nombre de colonne de la matrice de résultat. Ainsi, les lignes de calcul de taille comportent tout d'abord la déclaration d'une ou plusieurs variables, appelées variables de dimension, destinées à contenir le nombre de lignes et de colonnes de la matrice de résultat. Dans l'exemple décrit, les lignes de dimensionnement comportent une déclaration d'un premier entier, nommé dup_52_nr dans le code, destiné à contenir le nombre de lignes de la matrice de résultat, et une déclaration d'un second entier, nommé dup_52_nc dans le code, destiné à contenir le nombre de colonnes de la matrice de résultat. Les lignes de calcul de taille comportent en outre un ou des appels à la ou aux fonctions de calcul des dimensions de la matrice de résultat déterminées à l'étape 220. Les lignes de calcul de taille comportent en outre une ou des affectations des résultats de la ou des fonctions de calcul des dimensions de la matrice de résultat à ou aux variables de dimension de la matrice de résultat. Dans l'exemple décrit, pour le calcul matriciel « conj(A) + B », les lignes de calcul de taille insérées sont donc : int dup_52_nr; int dup_52_nc; dup_52_nr = max_sz(A.p_nr, B.p_nr); dup_52_nc = max_sz(A.p_nc, B.p_nc); Au cours d'une étape 222, le pré-compilateur 112 détermine et insère, dans le code source, pour chaque calcul matriciel dont la présence a été déterminée, une ou plusieurs lignes de code, appelées lignes d'allocation, destinées à être compilées en instructions qui, lorsqu'exécutées par le processeur 114, allouent un espace mémoire à la matrice de résultat à partir des dimensions, qui on été calculées, de la matrice de résultat. Dans l'exemple décrit, la ligne d'allocation comporte un appel à la primitive d'initialisation de matrice ra_init_size, à laquelle la matrice résultat du calcul matriciel et la ou les variables de dimension de la matrice de résultat sont passées comme arguments. Dans l'exemple décrit, pour le premier bloc de calcul matriciel, la ligne 10 d'allocation est ainsi : ra_init_size(C, dup_52_nr, dup_52_nc); Au cours d'une étape 224, le pré-compilateur 112 détermine et insère, dans le code source, à la place de chaque calcul matriciel dont la présence a été déterminée, une ou plusieurs lignes de code, appelées lignes de 15 commande, destinées à être compilées en instructions qui, lorsqu'exécutées par le processeur 114, commandent le dispositif électronique spécialisé 116, afin que ce dernier réalise le calcul matriciel. Dans l'exemple décrit, la ou les lignes de commande sont destinées à être compilées en instructions qui, lorsqu'exécutées par le processeur 114, 20 transmettent au dispositif électronique spécialisé 116 les matrices d'entrée et les opérations matricielles du calcul matriciel. Dans l'exemple décrit, la ligne de commande comporte un appel à la primitive ra_array_prim_core, à laquelle la matrice de résultat, les matrices d'entrée et les opérations du calcul matriciel sont passés comme arguments. 25 Dans l'exemple décrit, pour le premier bloc de calcul matriciel, la ligne de code d'appel de primitive est : ra array_prim_core(C, "", "operator+", "conj", A, "nulcfg", B); Ainsi, dans l'exemple décrit, le code source à l'issue de l'étape 214 est le suivant, les lignes ajoutées ou modifiées étant indiquées en gras : 30 void example_compilation (int N) Array A; ra_fl (A); Array B; ra f2(B); Array C; int dup_52_nr; int dup_52_nc; dup_52_nr = max_sz(A.p_nr, B.p_nr); dup_52_nc = max_sz(A.p_nc, B.p_nc); ra_init_size(C, dup_52_nr, dup_52_nc); ra_array_prim_core(C, '1", "operator+", "conj", A, "nulcfg", B); Array D; int dup_53_nr; int dup_53_nc; dup_53_nr = max_sz(A.p_nr, B.p_nr); dup_53_nc = max_sz(A.p_nc, B.p_nc); 15 ra_init_size(D, dup_53_nr, dup_53_nc); ra_array_prim_core(D, "operator+", "nulcfg", A, "opp", B); Array E; int dup_54_nr; int dup_54_nc; 20 dup_54_nr = max_sz(A.p_nr, B.p_nr); dup_54_nc max_sz(A.p_nc, B.p_nc); ra_init_size(E, dup_54_nr, dup_54_nc); ra_array_prim_core(E, "", "operator>", "nulcfg", C, "nulcfg", D); } 25 Au cours d'une étape 226, le pré-compilateur 112 simplifie les lignes du code source et en particulier les lignes insérées à l'étape 214. Ainsi, au cours des étapes 214 et 226, il a été inséré, dans le code source, les lignes déterminées à l'étape 214 (ligne de calcul de taille, d'allocation et de commande) et simplifiées à l'étape 226. Dans l'exemple décrit, plusieurs étapes de simplification sont 5 réalisées au cours de l'étape 226. Au cour d'une étape 228, le pré-compilateur 112 recherche, en particulier dans les lignes insérées, l'affectation d'une même expression à deux variables différentes. L'expression est par exemple un appel de fonction, dont le résultat est ainsi affecté aux deux variables. 10 Dans l'exemple décrit, le pré-compilateur 112 trouve les lignes indiquées en gras : void example_compilation (int N) Array A; ra fl(A); 15 Array B; ra_f2(B); Array C; int dup_52_nr; int dup_52_nc; 20 dup_52_nr = max_sz(A.p_nr, B.p_nr); dup_52_nc = max_sz(A.p_nc, B.p_nc); ra_init_size(C, dup_52_nr, dup_52_nc); ra_array_prim_core(C, "", "operator+", "conj", A, "nulcfg", B); Array D; 25 int dup_53_nr; int dup_53_nc; dup_53_nr = max_sz(A.p_nr, B.p_nr); dup_53_nc = max_sz(A.p_nc, B.p_nc); ra init size(D, dup_53_nr, dup_53_nc); 30 ra_array_prim_core(D, "", "operator+", "nulcfg", A, "opp", B); Array E; int dup_54_nr; int dup_54_nc; dup_54_nr = max_sz(A.p_nr, B.p_nr); dup_54_nc = max_sz(A.p_nc, B.p_nc); ra_init_size(E, dup_54_nr, dup_54_nc); ra_array_prim_core(E, "", "operator>", "nulcfg", C, "nulcfg", D); } Au cours d'une étape 230, le pré-compilateur 112 supprime l'affectation d'une première des deux variables et remplace, dans le code source, cette première variable par la seconde variable. Le pré-compilateur 112 supprime également la déclaration de la première variable. Dans l'exemple décrit, le code source à l'issue de l'étape 230 est donc le suivant void example_compilation (int N) { Array A; ra_fl(A); Array B; ra f2(B); Array C; int dup_52_nr; int dup_52_nc; dup_52_nr = max_sz(A.p_nr, B.p_nr); dup_52_nc = max_sz(A.p_nc, B.p_nc); ra _ init size(C, dup_52_nr, dup_52_nc); _ ra_array_prim_core(C, "", "operator+", "conj", A, "nulcfg", B); 25 Array D; ra_init_size(D, dup_52_nr, dup_52_nc); ra _ array _ prim _core(D, "", "operator+", "nulcfg", A, "opp", B); Array E; ra_init_size(E, dup_52_nr, dup_52_nc); 30 ra_array_prim_core(E, "", "operator>", "nulcfg", C, "nulcfg", D); } Les étapes 228 et 230 permettent donc de diminuer le nombre d'affectations du code source. Dans le cas ou l'expression est un appel de fonction, ces étapes permettent également de supprimer les appels de fonctions redondants du code source. Ces étapes permettent également de diminuer le nombre de variables utilisées. Au cours d'une étape 232, le pré-compilateur 112 recherche une combinaison d'appels de fonction associée à l'une parmi plusieurs règles prédéterminées de simplification. Une règle de simplification associée à la combinaison max_sz (max_sz(a, 1), b) est par exemple : max_sz (max_sz(a, 1), b) = max_sz(a, b). Au cours d'une étape 234, le pré-compilateur 112 simplifie chaque combinaison trouvée selon la règle de simplification associée. Dans l'exemple décrit, le code source à l'issue de l'étape 234 est le suivant : void example_compilation (int N) { Array A; ra_fl(A); Array B; raf2(B); Array C; int dup_52_nr; int dup_52_nc; dup_52_nr = max_sz(A.p_nr, B.p_nr); dup_52_nc = max_sz(A.p_nc, B.p_nc); ra _ init size(C, dup_52_nr, dup_52_nc); _ ra array _ prim _core(C, "", "operator+", "conj", A, "nulcfg", B); _ Array D; ra_init_size(D, dup_52_nr, dup_52_nc); ra_array_prim_core(D, "", "operator+", "nulcfg", A, "opp", B); Array E; ra_init_size(D, dup_52_nr, dup_52_nc); ra_array_prim_core(E, "", "operator>", "nulcfg", C, "nulcfg", D); } 2 9863 4 3 21 Au cours d'une étape 236, le pré-compilateur 112 fournit au compilateur principal 114 le code source modifié. Au cours d'une étape 238, le compilateur principal 114 compile le code source fourni à l'étape 236, en code machine destiné à être exécuté par 5 le système informatique cible 112. L'invention n'est pas limitée aux exemples de mise en oeuvre décrits précédemment, mais au contraire définie par les revendications qui suivent. Il apparaîtra en effet à l'homme de l'art que diverses modifications peuvent être apportées aux exemples de mise en oeuvre décrits ci-dessus, à 10 la lumière de l'enseignement qui vient de lui être divulgué. En particulier, les calculs matriciels que la primitive de calcul matriciel est apte à calculer pourraient être conforme à une autre expression prédéterminée, par exemple : op1(op2(A), op3(op4(B), op5(C))), de sorte que les lignes suivantes : 15 D = A - B; E = C > D; formeraient un bloc de calcul matriciel correspondant au calcul matriciel : E = C > A - B. Dans ce cas, le symbole d'opération op1 correspondrait à l'opération 20 >, le symbole d'opération op2 correspondrait à l'opération d'identité, le symbole d'opération op3 correspondrait à l'opération +, le symbole d'opération op4 correspondrait à l'opération d'identité et le symbole d'opération op5 correspondrait à l'opération d'opposée. Par ailleurs, dans les revendications qui suivent, les termes utilisés ne 25 doivent pas être interprétés comme limitant les revendications aux éléments des exemples de mise en oeuvre décrits précédemment, mais doivent être interprétés pour y inclure tous les équivalents dont la prévision est à la portée de l'homme de l'art en appliquant ses connaissances générales. REVENDICATIONS1. Procédé de pré-compilation d'un code source écrit dans un langage informatique et comportant des lignes de code, caractérisé en ce qu'il comporte - la détermination (212), dans le code source, de la présence d'un au plusieurs calculs matriciels sur une ou plusieurs matrices, appelées matrices d'entrée, dont le résultat est affecté à une matrice, appelée matrice de résultat, la modification (214) du code source en fonction du ou des calculs matriciels dont la présence a été déterminée. 2. Procédé de pré-compilation selon la revendication 1, dans lequel la modification (214) du code source comporte : la détermination (216), pour chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes de calcul de taille, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur (114), calculent les dimensions de la matrice de résultat à partir d'au moins une des dimensions d'au moins une matrice d'entrée. 3. Procédé de pré-compilation selon la revendication 2, dans lequel 20 la modification (214) du code source comporte : la détermination (222), pour chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes d'allocation, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur (114), 25 allouent un espace mémoire à la matrice de résultat à partir des dimensions de la matrice de résultat qui ont été calculées. 4. Procédé de pré-compilation selon la revendication 2 ou 3, comportant en outre : - la simplification (226) des lignes déterminées pour diminuer le 30 nombre de fonctions et/ou de variables présentes dans ces 2 9863 4 3 23 lignes, les lignes simplifiées étant insérées dans le code source. 5. Procédé de pré-compilation selon la revendication 4, dans lequel la simplification (226) des lignes comporte : 5 la détermination (228), dans les lignes, de l'affectation d'une même expression à deux variables différentes, la suppression (230) de l'affectation d'une première des deux variables et le remplacement, dans les lignes, de la première variable par la seconde des deux variables. 10 6. Procédé de pré-compilation selon la revendication 4 ou 5, dans lequel la simplification (226) des lignes comporte : la détermination (232) de la présence, dans la ou les lignes de calcul de taille, d'une combinaison d'appels de fonction d'au moins une dimension d'au moins une matrice d'entrée, 15 la simplification (234) de la combinaison d'appels de fonction à partir de règles prédéterminées de simplification de combinaisons d'appels de fonction. 7. Procédé de pré-compilation selon l'une des revendications 1 à 6, dans lequel la modification (214) du code source comporte : l'insertion (224), dans le code source, à la place de chaque calcul matriciel dont la présence a été déterminée, d'une ou plusieurs lignes de code, appelées lignes de commande, destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur (114), commandent un dispositif électronique (116), différent du processeur (114), spécialisé pour réaliser le calcul matriciel, afin que ce dispositif électronique spécialisé (116) réalise le calcul matriciel. 8. Procédé de pré-compilation selon la revendication 7, dans lequel le ou les calculs matriciels dont la présence est déterminée appartiennent chacun à une liste prédéterminée de calculs matriciels, et dans lequel le dispositif électronique (116) est spécialisé pour réaliser chacun des calculs matriciels de la liste prédéterminée. 2 9 86 3 4 3 24 9. Procédé de pré-compilation selon la revendication 8, dans lequel les calculs matriciels de la liste prédéterminée sont des calculs matriciels conformes à une expression prédéterminée. 10. Procédé de pré-compilation selon l'une des revendications 7 à 9, 5 dans lequel la ou les lignes de commande sont destinées à être compilées en instructions qui, lorsqu'exécutées par un processeur (114), transmettent au dispositif électronique spécialisé (116) les matrices d'entrée et les opérations matricielles du calcul matriciel. 11. Procédé de pré-compilation selon la revendication 3 et l'une des 10 revendications 7 à 10, dans lequel l'allocation d'un espace mémoire pour la matrice de résultat est réalisée dans une mémoire (118) du dispositif électronique spécialisé (116), ce dernier étant destiné à écrire le résultat du calcul matriciel dans l'espace mémoire alloué. 12. Procédé de compilation comportant, d'une part, un procédé de 15 pré-compilation selon l'une des revendications 1 à 11, et, d'autre part : la compilation (238) du code source modifié au cours du procédé de pré-compilation en code machine destiné à être exécuté par un système informatique, appelé système informatique cible (112). 20 13. Programme d'ordinateur comportant des instructions qui, lorsqu'exécutés par un processeur (102) d'un système informatique, entraînent la mise en oeuvre d'un procédé de pré-compilation selon l'une des revendications 1 à 11, ou bien d'un procédé de compilation selon la revendication 12. 25 14. Système informatique comportant : un processeur (102), une mémoire vive (106), et une mémoire de masse (104) dans laquelle est enregistré un programme d'ordinateur (110) selon la revendication 13 30 destiné à être chargé en mémoire vive (106) pour être exécuté par le processeur (102).