J'écris un jeu à jouer au jeu (Aichaallenge.org - fourmis), ce qui nécessite beaucoup de mettre à jour et de faire référence à des structures de données. J'ai essayé les matrices et les cartes, mais le problème de base semble être que chaque mise à jour crée une nouvelle valeur, ce qui le rend lent. Le jeu vous démarque si vous prenez plus d'une seconde pour faire votre déménagement, la demande compte donc comme «difficile-réel». Est-il possible d'avoir la performance des structures de données mutables dans HASKELLL, ou devrais-je apprendre Python ou réécrire mon code dans OCAML?
J'ai complètement réécrit les fourmis "Starter-Pack". Changé des tableaux aux cartes car mes tests ont montré que les cartes sont à jour beaucoup plus rapidement. P>
J'ai dirigé la version de cartes avec profilage sur, ce qui a montré qu'environ 20% du temps est pris par la carte des mises à jour seules. p>
Voici une simple démonstration de la mise à jour de la matrice lente sommes. P>
import qualified Data.Vector.Unboxed.Mutable as V fast_vector :: IO (V.IOVector Int) fast_vector = do vec <- V.new 10000 V.set vec 0 mapM_ (\i -> V.write vec i i) [0..9999] return vec fv_read :: IO Int fv_read = do v <- fast_vector V.read v 9999
3 Réponses :
Tout d'abord, pensez si vous pouvez améliorer votre algorithme. Notez également que la valeur par défaut Deuxièmement, vous devez utiliser un profileur a > Pour trouver où le problème de la performance est au lieu de s'appuyer sur l'agglomération de la main. Le code Haskell est généralement beaucoup plus rapide que Python (10-30 fois plus rapide, vous pouvez regarder Shootout linguistique par exemple de comparaison) Même avec des structures de données fonctionnelles, vous faites donc probablement quelque chose de mal. P>
haskell prend en charge les données mutables assez bien. Voir Utilisez-vous code compilé (par exemple Assurez-vous également que vous avez une optimisation allumée ( ants.hs code> n'est pas optimale et que vous devez rouler votre propre. P>
St code> (fil d'état) et bibliothèques pour des tableaux mutables pour le
St code>. Jetez également un coup d'œil à Vecteurs Package. Enfin, vous pouvez utiliser HASKELL DATA-Parallel, HASKELL-MPI ou Autres façons de la parallélisation à Chargez tous les cœurs CPU disponibles, ou même distribuer des travaux sur plusieurs ordinateurs. P>
Cabal Build code> ou
GHC --Make code>) ou utilisez
runhakell code> ou
ghci code >? Ces derniers sont des interprètes byTecode et créent un code beaucoup plus lent que le compilateur de code natif. Voir Référence Cabal - C'est le moyen préféré de construire des applications. P>
-O2 code> et d'autres drapeaux ). Notez que
-o code> vs
-O2 code> peut faire la différence et essayer différents backends, y compris le nouveau backend LLVM (
-fllvm code>). P >
Le code est compilé et j'ai couru avec le profilage. Rien n'alluminant, sauf que la mise à jour des structures de données prend 30% +. En regardant dans le fil de l'état, merci.
Vous demandez essentiellement une structure de données mutable. En dehors des bibliothèques standard, je vous recommanderais de rechercher ceci: p>
Cela dit, je ne suis pas si sûr que vous en avez besoin. Il existe également des algorithmes neat pour des structures de données pertinentes. Un remplacement rapide pour les données.MAP est la table de hachage de ce package: P>
Les conteneurs non ordonnés sont des structures de données immuables avec hachage. (Vector a des vecteurs mutables et immuables)
Teneur, avez-vous une référence pour ces algorithmes "soignés"?
@ Grego'keefe - Le lien des conteneurs non-commandés conduit à une très bonne implémentation de carte persistante. Sinon, la thèse de Chris Okasaki et le travail ultérieur ( CS.CMU.EDU/~RWH /theses/okasaki.pdf ) est un bon point de départ. Voir aussi cette question sur stackexchange: cstheory.stackexchange.com/questions/1539/...
Merci John, d'excellentes références. J'ai commencé à absorber ce genre de choses, bien que cela puisse prendre un peu de temps!
Mise à jour des tableaux Un élément à la fois est incroyablement inefficace car chaque mise à jour implique de faire une copie de l'ensemble de l'ensemble. D'autres structures de données telles que la carte code> sont implémentées comme des arbres et permettent ainsi des mises à jour de l'heure logarithmique. Cependant, dans la mise à jour générale des structures de données fonctionnelles, un élément à la fois est souvent sous-optimal, vous devriez donc essayer de prendre un pas en arrière et de réfléchir à la manière dont vous pouvez mettre en œuvre quelque chose comme une transformation de toute la structure à la fois au lieu d'un seul élément. à la fois.
Par exemple, votre exemple Si vous ne pouvez pas penser à une alternative à l'algorithme impératif d'un élément à un élément à l'autre, des structures de données mutables ont été mentionnées comme une autre option. P> P> SLOW_ARRAY CODE> peut être écrit beaucoup plus efficacement en effectuant toutes les mises à jour en une étape, ce qui nécessite uniquement la copie de la matrice une fois. P> < Pré> xxx pré>
Modifiez la question pour réfléchir que vous avez utilisé le profileur et fournissez à Wuth certains échantillons de code autonome lent, si cela est possible. Ma réponse est générique et une question bien écrite peut attirer des gens couramment le réglage de la performance.
"Est-il possible d'avoir la performance de structures de données mutables dans HASKELLL?" La réponse est oui! Haskell peut faire ça!