Fondements scientifiques
Mots clés : évaluation partielle,
spécialisation, transformation de programmes, systèmes
adaptatifs, génie logiciel .
- Évaluation partielle
- transformation de programmes qui a pour but de
spécialiser un programme en fonction de certaines de ses
données d'entrée.
Résumé :
Le projet s'intéresse à la conception de systèmes
adaptatifs. Notre démarche consiste à rendre performant un
programme générique en le spécialisant en fonction d'un
contexte donné d'utilisation. Plus précisément, notre
objectif est d'étudier les techniques de spécialisation et
leur utilisation pour des applications de taille réelle. En
particulier, l'évaluation partielle est à la base de notre
approche de conception de programmes et de systèmes
adaptatifs.
L'adaptabilité est devenue une caractéristique
incontournable dans la conception des nouveaux logiciels pour
leur permettre de répondre à des besoins fondamentaux tels
que :
- l'évolution et l'hétérogénéité des matériels
informatiques, ainsi que la prise en compte de leurs
caractéristiques de bas niveau ;
- la généralité sans cesse croissante des problèmes que
doivent traiter les logiciels pour contrebalancer leur coût
de développement ;
- le besoin d'intégration avec d'autres composants
logiciels pour constituer des systèmes informatiques
complets.
Des techniques de conception de logiciels adaptatifs
existent déjà ; elles consistent généralement à
structurer un logiciel de telle sorte qu'il puisse évoluer en
fonction de son contexte d'utilisation. Cette structuration
prend, traditionnellement, la forme de modules et de
couches logicielles. L'évolution de ces techniques
s'est traduite par un réel engouement pour les langages à
objets dont l'un des objectifs principaux est d'offrir des
mécanismes d'organisation et de généralisation de composants
logiciels. Plus récemment, des approches reposant sur la
notion de bus logiciel ont été proposées pour permettre la
composition de composants logiciels indépendants, mais dont
l'interface est spécifiée.
Toutefois, les approches existantes sont incomplètes car,
bien qu'elles prennent en compte les aspects conceptuels d'un
logiciel, elles négligent ses aspects relatifs à
l'implémentation. Par faute de méthodes et d'outils adéquats,
l'adaptabilité se traduit souvent par l'introduction, dans la
mise en oeuvre, de mécanismes tels que l'interprétation (de
paramètres ou d'un état global), la protection des données et
du code, et la copie de données entre différentes couches
logicielles. Ces mécanismes complexifient les algorithmes et
entraînent une inefficacité importante qui conduit bien
souvent à spécialiser manuellement un logiciel pour un
contexte d'utilisation donné afin d'obtenir des performances
acceptables. Cette spécialisation manuelle est bien
évidemment fastidieuse et source d'erreurs. De plus, elle
multiplie les versions d'un même logiciel entraînant du même
coup des problèmes de maintenance. Plus généralement, elle
annule les efforts d'adaptabilité du logiciel déployés lors
de sa conception.
Notre objectif est d'étudier la généralisation et la
systématisation des techniques de spécialisation et leur
utilisation pour des applications de taille réelle.
L'évaluation partielle est à la base de notre approche de
conception de programmes et systèmes adaptatifs, nous en
présentons maintenant ses aspects fondamentaux.
L'évaluation partielle a pour but de spécialiser un
programme en fonction de certaines de ses données d'entrée.
Cette transformation de programmes préserve la sémantique
initiale dans la mesure où le programme spécialisé,
appliqué aux données manquantes, produit le même résultat que
le programme original appliqué à toutes les données. Comme on
aime à le souligner, la calculabilité de l'évaluation
partielle repose sur le théorème Smn de Kleene
[JSS89,Kle52].
À la différence d'une stratégie de transformation de
programmes générale à la Burstall et Darlington [BD77], l'évaluation partielle a pour unique
objectif la spécialisation de programmes. Un évaluateur
partiel consiste en un ensemble réduit de règles de
transformation de programmes visant à évaluer les expressions
qui manipulent des données disponibles et à reconstruire les
expressions dépendant des données manquantes.
Bien que simple dans son principe, la notion de
spécialisation s'applique à une vaste classe de problèmes. En
effet, l'évaluation partielle a été utilisée pour des
applications aussi variées que la génération de compilateurs
à partir d'interprètes [JSS89], l'optimisation de programmes
numériques [Ber90], le filtrage [CD89] et l'instrumentation de
programmes [KHC91].
Pour présenter l'évaluation partielle, il est important
d'établir une distinction entre un programme et la fonction
(c'est-à-dire l'objet mathématique) que ce programme dénote.
Pour ce faire nous utilisons la convention suivante :
lorsque le nom d'une variable apparaît en majuscule, cette
variable dénote un programme, sinon elle dénote une fonction.
Nous ne définissons pas la correspondance entre un programme
et la fonction qu'il dénote ; nous supposons que cette
correspondance est donnée par la sémantique formelle du
langage. Nous supposons de plus qu'il existe un évaluateur
eval tel que :
eval (P, d )= p d
Etant donné un programme P à deux entrées et une valeur
v, un évaluateur partiel est
un programme, noté PE,
calculant le programme résiduel Pv
Pv = eval (PE,(P,
v))
tel que, lorsque le programme résiduel est appliqué à la
donnée manquante w
eval (
Pv,
w)
eval
(
P,(
v,
w))
le programme original et le programme spécialisé
produisent le même résultat. D'un point de vue fonctionnel,
ceci peut être écrit comme suit :
pv(
w)
p(
v,
w)
où Pv =
pe(
P,
v)
Les données disponibles pendant l'évaluation partielle
sont dites statiques (la donnée v). Les données manquantes sont dites
dynamiques (la donnée w) [JSS89]. On dit que Pv est la version spécialisée
de P en fonction de
v.
Il est également possible d'optimiser le processus même
d'évaluation partielle par auto-application de l'évaluateur
partiel.
On distingue communément deux stratégies d'évaluation
partielle : en ligne et hors ligne. La
première stratégie consiste à déterminer le traitement du
programme au fur et à mesure de la phase d'évaluation
partielle. Les évaluateurs partiels basés sur ce principe ont
l'avantage de manipuler des valeurs concrètes, et donc,
peuvent déterminer précisément le traitement de chaque
expression d'un programme. Toutefois, ce processus est
coûteux : l'évaluateur partiel doit analyser le contexte
du calcul (c'est-à-dire les données disponibles) pour
sélectionner la transformation de programmes appropriée.
Cette opération est effectuée de façon répétitive dans le cas
de fonctions récursives, par exemple. Il n'est donc pas
surprenant de constater que les performances d'un évaluateur
partiel en ligne se dégradent rapidement lorsque de nouvelles
transformations de programmes sont introduites.
La deuxième stratégie d'évaluation partielle comporte deux
phases : une analyse de temps de liaison et une
phase de spécialisation [JSS89]. Étant donné un programme et une
description de ses entrées (statique/dynamique), l'analyse de
temps de liaison détermine les expressions qui peuvent être
évaluées lors de la phase d'évaluation partielle et celles
qui doivent être reconstruites : les premières sont
dites statiques, les autres dynamiques. Les informations de
temps de liaison sont valides tant que la description des
entrées du programme reste inchangée. Les expressions
statiques et dynamiques étant connues à l'avance, la phase de
spécialisation est plus efficace. Toutefois, l'analyse de
temps de liaison, manipulant des valeurs abstraites, permet
d'effectuer certaines approximations. Ainsi, le degré de
spécialisation d'une stratégie hors ligne peut être moindre
que celui d'une stratégie en ligne.
L'activité importante qui s'est développée dans le domaine
de l'évaluation partielle a conduit à la réalisation de
nombreux prototypes pour une variété de langages de
programmation tels que Scheme [Bon90,Con93b], C [And94] et Pascal [Mey91].
Traditionnellement, l'évaluation partielle est une
transformation effectuée sur le texte d'un programme. De ce
fait, elle intervient à la compilation et ne peut exploiter
que les valeurs disponibles à ce stade.
Nous avons développé un cadre de travail général
permettant de réaliser la spécialisation de programmes
impératifs à l'exécution [4]. Le processus de spécialisation que nous
avons conÇu a pour point de départ un programme annoté
d'actions. Ces actions décrivent les transformations à
effectuer sur chaque construction du programme à spécialiser
et, de fait, peuvent être vues comme une description de
l'ensemble des programmes qui peuvent être produits par
spécialisation. Notons que ce point de départ n'est pas
spécifique à la spécialisation à l'exécution ; dans
notre approche, les actions sont également utilisées pour
guider la spécialisation à la compilation.
À partir d'un programme annoté d'actions, nous produisons
automatiquement à la compilation des fragments de code
source. Ces fragments de code source sont incomplets dans la
mesure où les invariants ne sont connus qu'à l'exécution. Ils
sont transformés de manière à pouvoir être traités par un
compilateur standard. À l'exécution, il ne reste plus qu'à
sélectionner et copier certains de ces fragments de code,
insérer les valeurs dynamiques et reloger certains sauts pour
obtenir une spécialisation donnée.
Ces opérations sont simples et permettent donc un
processus de spécialisation très efficace qui ne nécessite
qu'un nombre limité d'exécutions du programme spécialisé
avant d'être amorti.
Les principes d'évaluation partielle décrits plus haut
permettent le développement rigoureux d'analyses de
programmes performantes [AC94,Con93a] et la conception de transformations de
programmes [CD90,CD91,Con93b] [2,14] pour des langages fonctionnels et
impératifs. Nos études conduisent à l'élaboration d'outils de
spécialisation. Ces outils ont un rÔle crucial dans la
validation de la technologie que nous développons. Nos
efforts actuels portent sur un système d'évaluation partielle
pour le langage C, Tempo (voir module 5.1). Par ailleurs,
nous avons entrepris le développement d'un frontal à Tempo,
permettant la spécialisation de programmes Java (voir
modules 5.2, 5.3 et 6.1).
Sous-sections