Memoization
Dans le calculant , le memoization est une technique de l'optimisation employée principalement pour accélérer les programmes informatiques en ayant des appels de fonction de que évitent de répéter le calcul des résultats pour les entrées précédent-traitées. Memoization a été également employé dans d'autres contextes (et pour d'autres buts que des gains de vitesse), comme dans le analysant . Bien que connexe au cachant , le memoization se rapporte à un cas spécifique de cette optimisation, le distinguant des formes de mise en antémémoire telles que l'amortissement ou le remplacement de page .
Vue d'ensemble
Le " de limite ; memoization" ; a été inventé par le Donald Michie dans le 1968 et est dérivé du mémorandum latin ( de de mot du à être rappelé), et porte ainsi la signification des résultats de rotation de d'une fonction dans quelque chose être rappelé. tandis que le memoization de pourrait être confondu avec la mémorisation de (en raison du partagé apparenté), memoization a une signification spécialisée dans le calcul.
Un " memoized de fonction ; remembers" ; les résultats correspondant à un certain ensemble d'entrées spécifiques. Les appels suivants avec les entrées rappelées renvoient le résultat rappelé plutôt que le recalculant, de ce fait déplaçant le coût primaire d'un appel avec des paramètres donnés au premier appel fait à la fonction avec ces paramètres. L'ensemble d'associations rappelées peut être un ensemble à taille fixe commandé par un algorithme de remplacement ou un ensemble fixe, selon la nature de la fonction et de son utilisation. Une fonction peut seulement memoized si c'est Referentially transparent ; c'est-à-dire, seulement si appeler la fonction a l'exact le même effet que remplaçant cet appel de fonction par sa valeur de retour. (Les exceptions de cas spécial à cette restriction existent, cependant.) Tandis que connexe aux tables de consultation puisque le memoization emploie souvent de telles tables dans son exécution, le memoization diffère de la consultation de table pure parce que les tables que le memoization pourrait employer sont peuplées d'une manière transparente sur une base '' comme-nécessaire '' de .
Memoization est des moyens d'abaisser le temps du d'une fonction coûté en échange du coût de l'espace de ; c'est-à-dire, les fonctions memoized deviennent optimisées pour la vitesse de en échange d'une utilisation plus élevée de l'espace de mémorisation par ordinateur de du . Le " de temps/espace ; cost" ; des algorithmes a un nom spécifique dans le calcul : complexité informatique de . Toutes les fonctions ont une complexité informatique dans le temps (c. elles de prennent du temps de s'exécuter) et dans l'espace de .
Bien qu'une différence se produise (c., l'espace utilisé est vitesse gagnée), ceci diffère de quelques autres optimisations qui impliquent la différence du temps-espace, telle que la diminution de la résistance , de ce memoization sont un temps d'exécution plutôt que l'optimisation au moment de la compilation du . D'ailleurs, la diminution de la résistance remplace potentiellement une opération chère telle que la multiplication par une opération moins chère telle que l'addition, et les résultats en épargne peuvent être fortement non-portatif à travers les machines , tandis que le memoization est une stratégie non lié à un type de machine particulier du .
Considérer la fonction suivante du pseudo-code calculer le factoriel du n :
fonction factorielle (le n est un nombre entier non négatif) si le n est 0 alors renvoyer 1 la convention qui le '' ''' 0 ! = 1 ''' autrement factoriel de retour (n - 1) le n de périodes appellent factoriel avec le paramètre 1 moins que n '' finir si finir la fonction
Pour chaque n du nombre entier tels que le , le résultat final de la fonction factorial est le invariable ; si appelé comme x = factoriel (3), le résultat est tel que le X le sera toujours assigné la valeur 6. Une version non-memoized de ce qui précède, donnée la nature de l'algorithme récursif du impliqué, exigerait le n de + des invocations 1 de factorial à arriver à un résultat, et chacune de ces invocations, alternativement, a un coût associé dans le temps où il prend la fonction pour renvoyer la valeur calculée. Selon la machine, ce coût pourrait être la somme de :
le coût pour installer l'armature fonctionnelle de pile des appels.
factorial par le n . Dans une exécution non-memoized, le chaque appel supérieur de à factorial inclut le coût cumulatif d'étapes 2 à 6 proportionnels à la valeur initiale du n .
Une version memoized de la fonction de factorial suit :
fonction factorielle (le n est un nombre entier non négatif) assigner le provisoire X de variable de nombre entier si le n est en consultation-table de alors renvoyer le consultation-table-valeur-pour-n ; autrement si le n est 0 alors renvoyer 1 la convention qui le '' ''' 0 ! = 1 ''' autrement X = factoriel (n - 1) le n de périodes appellent factoriel avec le paramètre 1 moins que n '' finir si stocker le X en consultation-table de dans la fente du n th le résultat de n ! pour plus tard '' x de retour fonction de fin
Dans la version memoized ci-dessus, on assume que le lookup-table est un espace mémoire persistant, tel qu'une rangée associative qui emploie le n en tant que sa clef. Puisque cette table de consultation emploiera l'espace (c'est-à-dire, de mémorisation par ordinateur) de , le temps requis pour faire appel factorial à plusieurs reprises à un deuxième appel à la fonction avec le même paramètre a été commercé pour la mémoire exigée pour stocker la table de consultation.
Dans cet exemple particulier, si factorial est d'abord appelé avec 5, et alors appelé plus tard avec n'importe quelle valeur inférieur ou égal à cinq, ces valeurs de retour également memoized, puisque factorial se sera appelé périodiquement avec les valeurs 5, 4, 3, 2, 1, et 0, et les valeurs de retour pour le chaque de ceux auront été stockées. S'il s'appelle alors avec un nombre plus considérablement que 5, tels que 7, seulement 2 appels récursifs seront faits (7 et 6), et la valeur pour 5 ! aura été stocké de l'appel précédent. De cette façon, le memoization permet à une fonction de devenir temps-efficace plus il s'appelle plus souvent, ainsi ayant pour résultat le global certain accélérer .
Quelques autres considérations
Memoization automatique
Tandis que le memoization peut être ajouté au intérieurement de fonctions et le explicitement par un informaticien la version ci-dessus memoized de factorial est mis en application plus ou moins de la même façon, les fonctions transparentes de Referentially peuvent également être le automatiquement memoized extérieurement . Les techniques utilisées par Norvig font bléser l'application non seulement dans le terrain communal (la langue dans laquelle son article a démontré le memoization automatique), mais dans les divers autres langages de programmation des applications du memoization automatique également ont été formellement explorées dans l'étude de la réécriture de limite de et de l'intelligence artificielle .
Dans ces langages de programmation où les fonctions sont d'abord ou les objets de seconde classe (tel que Lua , avec ses fonctions de première classe), le memoization automatique peut être mis en application en remplaçant (à temps d'exécution ) une fonction par sa valeur calculée une fois qu'une valeur a été calculée pour un ensemble de paramètres indiqué. La fonction qui fait ce remplacement de valeur-pour-fonction-objet peut génériquement envelopper n'importe quelle fonction referentially transparente. Considérer le pseudo-code suivant (où on le suppose que les fonctions sont des valeurs de première classe) :
la fonction memoized-appellent (le F est un paramètre d'objet de fonction) si le F a aucun joint de rangée n'évalue alors assigner une rangée associative appelée les valeurs de ; attacher les valeurs de au F ; finir si ; si les valeurs de de F. '' est vide alors F. évalue '' = le F (arguments) ; finir si ; renvoyer les valeurs de de F. '' ; finir la fonction
Afin d'appeler une version automatiquement memoized de factorial using la stratégie ci-dessus, plutôt qu'appelant factorial directement, le code appelle le memoized-call (factoriel (le de n)). Chaque un tel appel vérifie d'abord pour voir si une rangée de support a été assignée pour stocker des résultats, et sinon, les attachés qui rangent. Si aucune entrée n'existe à la position values (où arguments sont employés pendant que la clef de la rangée associative), un vrai appel de de est fait à factorial avec les arguments fournis. En conclusion, l'entrée dans la rangée à la position clé est retournée au visiteur.
La stratégie ci-dessus exige le explicite de s'enveloppant à chaque appel à une fonction qui doit memoized. Dans ces langues qui permettent les fermetures , le memoization peut être effectué de implicitement par une usine du functor qui renvoie un objet memoized enveloppé de fonction. En pseudo-code, ceci peut être exprimé comme suit :
la fonction construisent-memoized-functor ( de F est un paramètre d'objet de fonction) assigner un objet de fonction appelé le de memoized-version de ; laisser la memoized-version (arguments) soit si l'individu de que le n'a aucune valeur jointe de rangée alors est une référence à [[ceci (de l'informatique)|ceci] objet ] assigner une rangée associative appelée les valeurs de ; attacher les valeurs de à l'individu de ; finir si ; s'individu. les valeurs de '' est vide alors individu. évalue '' = le F (arguments) ; finir si ; retourner l'individu. le évalue '' ; l'extrémité a laissé ; de retour de memoized-version de ; fonction de fin
Plutôt que l'appel factorial, un nouvel objet memfact de fonction est créé comme suit :
le memfact = construisent-memoized-functor (factoriel)
L'exemple ci-dessus suppose que la fonction factorial a déjà été défini avant que le l'appel à construct-memoized-functor soit fait. De ce point en avant, le memfact ( de n) s'appelle toutes les fois que le factoriel du de n est désiré. Dans les langues telles que le Lua , des techniques plus sophistiquées exister qui permettent à une fonction d'être remplacée par une nouvelle fonction avec le même nom, qui laisserait :
factoriel = construire-memoized-functor (factoriel)
Essentiellement, de telles techniques impliquent d'attacher le original d'objet de fonction de au functor créé et expédiant appelle à la fonction originale memoized par l'intermédiaire d'un nom d'emprunt quand un appel à la fonction réelle est exigé (pour éviter récursion sans fin ), comme illustré ci-dessous :
la fonction construisent-memoized-functor ( de F est un paramètre d'objet de fonction) assigner un objet de fonction appelé le de memoized-version de ; laisser le de memoized-version de (arguments) soit si l'individu de que le n'a aucune valeur jointe de rangée alors est une référence à [[ceci (de l'informatique)|ceci] objet ] assigner une rangée associative appelée les valeurs de ; attacher les valeurs de à l'individu de ; assigner un nouvel objet de fonction appelé le dit ; attacher le dit à l'individu de ; capacité postérieure d'appeler F indirectement '' individu. dit = F ; finir si ; s'individu. les valeurs de '' est vide alors individu. évalue '' = individu. dit (arguments) ; un appel direct à F '' finir si ; retourner l'individu. le évalue '' ; l'extrémité a laissé ; de retour de memoized-version de ; fonction de fin
(Note : Certaines des étapes montrées ci-dessus peuvent être implicitement contrôlées par la langue d'exécution et sont données pour l'illustration.)
Analyseurs
Memoization a été exploré comme analysant la stratégie de en 1991 par le Norvig , qui a démontré qu'un algorithme semblable à l'algorithme d'Earley de pourrait être produit en présentant le memoization automatique à un analyseur récursif de descente de de simple de la marche arrière . En 2002, il a été examiné dans la profondeur considérable par Ford sous la forme appelée le packrat de analysant .
Tandis que Norvig augmentait la puissance l'analyseur par le memoization, l'analyseur augmenté était toujours comme complexe de temps comme algorithme d'Earley, qui démontre un cas de l'utilisation du memoization pour quelque chose autre que l'optimisation de vitesse. Johnson et Dörre
Voir également
théorie de complexité informatique - plus d'information sur la complexité d'algorithme.
Diminution de la résistance - une optimisation du compilateur qui remplace une opération chère avec un équivalent, moins la chère.
Évaluation paresseuse - parts de quelques concepts avec le memoization.
Table de consultation - une structure de données principale utilisée dans le memoization.
Modèle Flyweight - un modèle de programmation , celui de conception de d'objet emploie également le genre de memoization
Notes et références
.
| Random links: | Partie de Jantantrik Bahujan Samaj | Homme de patin | Division nationale deux de ligue de 2005 | Avant de Chambre | Liste des clubs du football des femmes au Japon | Memoization |