10
votes

Haskell Mise à jour en temps réel et performance de recherche

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


2 commentaires

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!


3 Réponses :


12
votes

Tout d'abord, pensez si vous pouvez améliorer votre algorithme. Notez également que la valeur par défaut ants.hs n'est pas optimale et que vous devez rouler votre propre.

Deuxièmement, vous devez utiliser un profileur 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.

haskell prend en charge les données mutables assez bien. Voir St (fil d'état) et bibliothèques pour des tableaux mutables pour le St . 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.

Utilisez-vous code compilé (par exemple Cabal Build ou GHC --Make ) ou utilisez runhakell ou ghci ? 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.

Assurez-vous également que vous avez une optimisation allumée ( -O2 et d'autres drapeaux ). Notez que -o vs -O2 peut faire la différence et essayer différents backends, y compris le nouveau backend LLVM ( -fllvm ).


1 commentaires

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.



2
votes

Vous demandez essentiellement une structure de données mutable. En dehors des bibliothèques standard, je vous recommanderais de rechercher ceci:



4
votes

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 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 SLOW_ARRAY 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. < Pré> xxx

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.


0 commentaires