Article de reference

spécialisation des algorithmes d'exécution

En informatique , la spécialisation d'algorithmes à l'exécution est une méthodologie permettant de créer des algorithmes efficaces pour des tâches de calcul coûteuses de certain...

informatique , la spécialisation d'algorithmes à l'exécution est une méthodologie permettant de créer des algorithmes efficaces pour des tâches de calcul coûteuses de certains types. Cette méthodologie trouve son origine dans le domaine de la démonstration automatique de théorèmes et, plus précisément, dans le projet de démonstrateur de théorèmes Vampire .

L'idée s'inspire de l'utilisation de l'évaluation partielle pour optimiser la traduction de programmes. De nombreuses opérations fondamentales des démonstrateurs de théorèmes suivent le schéma suivant. Supposons que nous devions exécuter un algorithme dans une situation où une valeur de est fixée pour potentiellement plusieurs valeurs différentes de . Afin de le faire efficacement, nous pouvons chercher une spécialisation de pour chaque fixé , c'est-à-dire un algorithme tel que son exécution soit équivalente à celle de .

L'algorithme spécialisé peut s'avérer plus efficace que l'algorithme générique, car il exploite certaines propriétés spécifiques de la valeur fixe . En général, il permet d'éviter certaines opérations redondantes pour ce paramètre particulier . Notamment, on peut souvent identifier des tests vrais ou faux pour cette valeur , comme le déroulement de boucles et la récursivité.

Spécialisation avec compilation

L'algorithme spécialisé doit être représenté sous une forme interprétable.

Dans de nombreuses situations, notamment lorsque le calcul doit porter sur plusieurs valeurs consécutives d'une fonction, il peut être exprimé sous forme d'instructions machine pour une machine abstraite spéciale , et on dit alors qu'il est compilé . Le code peut ensuite être optimisé par des transformations préservant le résultat et reposant uniquement sur la sémantique des instructions de la machine abstraite.

Les instructions de la machine abstraite peuvent généralement être représentées sous forme d'enregistrements . Un champ de cet enregistrement, l' identificateur d'instruction (ou étiquette d'instruction ), identifie le type d'instruction ; par exemple, un champ entier peut être utilisé, chaque valeur entière correspondant à une instruction particulière. D'autres champs peuvent servir à stocker des paramètres supplémentaires de l'instruction ; par exemple, un champ pointeur peut pointer vers une autre instruction représentant une étiquette, si la sémantique de l'instruction requiert un saut. Toutes les instructions du code peuvent être stockées dans une structure de données parcourable , telle qu'un tableau , une liste chaînée ou un arbre .

L'interprétation (ou l'exécution ) se déroule en récupérant les instructions dans un certain ordre, en identifiant leur type et en exécutant les actions associées à ce type.

Dans de nombreux langages de programmation, tels que C et C++ , une simple switchinstruction permet d'associer des actions à différents identificateurs d'instruction. Les compilateurs modernes compilent généralement une switchinstruction avec des étiquettes constantes (par exemple, des entiers) issues d'un intervalle restreint en stockant l'adresse de l'instruction correspondant à une valeur dans la i-ème cellule d'un tableau spécial, ce qui constitue un moyen d'optimisation efficace. On peut exploiter cette propriété en choisissant des valeurs pour les identificateurs d'instruction parmi un petit intervalle de valeurs.

Spécialisation en données et algorithmes

Il arrive que de nombreuses instances de `std::create` soient destinées à un stockage à long terme et que les appels à `std::create` surviennent avec différents `std::create` dans un ordre imprévisible. Par exemple, il peut être nécessaire de vérifier d'abord `std::create`, puis `std::create` , puis `std::create` , et ainsi de suite. Dans de telles circonstances, une spécialisation complète avec compilation peut s'avérer inadaptée en raison d'une consommation excessive de mémoire. Cependant, il est parfois possible de trouver une représentation spécialisée compacte pour chaque `std ::create`, qui peut être stockée avec `std::create` ou à la place de `std::create` . Nous définissons également une variante qui fonctionne sur cette représentation et dans laquelle tout appel à `std::create` est remplacé par `std::create` , conçu pour effectuer la même tâche plus rapidement.