Julia (Julia-lang) Performance comparée à Fortran et Python

j'ai adapté un programme simple pour calculer et tracer les vortex du mouvement de Julia pour tester le langage, Je l'ai aussi écrit en Python sans raison particulière.

(Avertissement: 1. Chaque comparaison de performance sur stackoverflow que j'ai Lu se fait gronder pour n'être pas complet/correct/bien écrit/pertinent etc. etc. - Je ne prétends pas que c'est une vraie comparaison, je voudrais juste savoir comment rendre la Julia plus rapide. 2. Je sais que le python pourrait être optimisé, implémenté dans Cython etc, cela ne fait pas partie de cette discussion, il est juste ici pour une référence de fonctions équivalentes en Julia et Python.)

Le code de performance et résultats on peut le voir en résumé.

la performance de Julia est significativement plus lente que celle de Fortran. Les temps pris pour effectuer le calcul lui-même sont (50000 pas de temps):

Fortran: 0.051s
Julia: 2.256s
Python: 30.846s

Julia est beaucoup plus lente (~44 fois lente) que Fortran, l'écart se rétrécit mais est toujours significatif avec 10 fois plus de pas de temps( 0.50s vs 15.24s).

Ces résultats sont significativement différents de ceux indiqués sur julia page d'accueil. Ce que je fais mal? Puis-je réparer la Julia pour qu'elle soit beaucoup plus rapide?

j'ai écrémé lire le Julia Conseils De Performances la page et le code-behind de la comparaison sur le Julia page d'accueil et rien n'est permanent à me corriger.

il est aussi intéressant de noter que Julia est extrêmement lente à charger ( 5secs ish!!) et beaucoup plus lent que Python pour lire le fichier texte. Puis-je faire quelque chose pour améliorer ces choses?

notez que les temps ci - dessus ne montrent pas le temps de chargement pour Julia et Python, c'est juste le temps brut pris pour L'AFAIK de calcul-voir le code. Pour fortran, c'est l'ensemble de la chose. Le pointage a été désactivé, à peu près, dans chaque cas pour permettre la comparaison de vitesse.

ordinateur: Intel i7-3770, 16 Go ram, SSD HD, OS: Ubuntu 13.10 64bit., Fortran: gfortran, GNU Fortran (Ubuntu / Linaro 4.8.1-10ubuntu9) 4.8.1, Julia: Version 0.3.0-prerelease+396 (2013-12-12 00:18 UTC), Commit c5364db* (0 days old master), x86_64-linux-gnu, Python: 2.7.5+


mise à Jour:

sur le Conseil d'ivarne j'ai réécrit le script Julia (mis à jour dans gist ci-dessus): encapsuler le travail grognon dans les fonctions, déclarer le type de tout et diviser les différents éléments de matrices en différents tableaux le cas échéant. (J'ai inclus Float64 dans un bon nombre d'endroits comme J'ai essayé Float32 pour voir si cela a aidé, il n'a pas la plupart du temps).

Les résultats sont comme suit:

50,000 pas de temps:

Fortran: 0.051s (entire programme)
Julia: raw calc.: 0.201s, calc. and return (?): 0.758s, total exec.: 6.947s

500,000 pas de temps:

Fortran: 0.495s (entire programme)
Julia: raw calc.: 1.547s, calc. and return (?): 2.094s, total exec.: 8.521s

en conclusion:

  • Vous pouvez accélérer Julia un peu.

  • vous pouvez affecter significativement la vitesse apparente de Julia en fonction de la façon dont vous le mesurez. performance.

25
demandé sur Wilfred Hughes 2013-12-16 18:54:56
la source

2 ответов

j'ai suivi le projet Julia depuis un moment maintenant, et j'ai quelques commentaires au code qui pourraient être pertinents.

  • Il semble que vous exécutez une quantité importante de code dans la portée globale. L'environnement global est actuellement très lent dans Julia, parce que les types toutes les variables doivent être vérifiées sur chaque itération. Les boucles doivent généralement être écrites dans une fonction.
  • vous semblez utiliser le découpage par réseau. Actuellement Cela fait une copie parce que Julia n'a pas rapide de la Matrice de points de vue. Vous pouvez essayer de les changer pour subarray, mais ils sont actuellement beaucoup plus lents qu'ils devraient.

le temps de chargement de PyPlot (et de tout autre paquet) est un problème connu, et est dû au fait que l'analyse et la compilation du code Julia en code machine, prennent beaucoup de temps. Il y a des idées pour avoir une cache pour ce processus afin que ce processus devienne instantané, mais il n'est pas encore terminé. La bibliothèque de Base est actuellement mise en cache dans l'état compilé, donc la plupart des l'infrastructure est sur la branche master maintenant.

ajouté: J'ai essayé de faire le test dans une fonction isolée et j'ai eu ces résultats. Voir cette gist

Analyse:

elapsed time: 0.334042578 seconds (11797548 bytes allocated)

et les runes d'arbre consécutives de la boucle d'essai principale.

elapsed time: 0.62999287 seconds (195210884 bytes allocated)
elapsed time: 0.39398753 seconds (184735016 bytes allocated)
elapsed time: 0.392036875 seconds (184735016 bytes allocated)

remarquez comment le timing s'est amélioré après la première exécution, parce que le code compilé a été utilisé de nouveau.

mise à Jour 2 Avec une meilleure gestion de la mémoire (assurer la réutilisation des tableaux, parce que la tâche ne copie pas), j'ai obtenu le timing à 0.2 secondes (sur ma machine). Il est certainement plus qui pourrait être fait pour éviter d'allouer de nouveaux tableaux, mais alors il commence à être un peu délicat.

Cette ligne ne fait pas ce que vous en pensez:

vx_old = vx

mais cette faire ce que vous voulez:

copy!(vx_old, vx)

et dévectoriser une boucle.

x += 0.5*(vx + vx_old)*delta_t
y += 0.5*(vy + vy_old)*delta_t

à:

for i = 1:nvortex
    x[i] += 0.5*(vx[i] + vx_old[i])*delta_t
    y[i] += 0.5*(vy[i] + vy_old[i])*delta_t
end
20
répondu ivarne 2015-08-07 12:33:57
la source

@ivarne couvre ceci mais il porte un peu plus d'attention:

julia> @time x=[1:10000];
elapsed time: 1.544e-5 seconds (80120 bytes allocated)

julia> @time y = x[1:10000];
elapsed time: 2.6857e-5 seconds (80120 bytes allocated)

Wow. C'est beaucoup de temps et de mémoire.

julia> @time z = sub(x,1:10000);
elapsed time: 6.239e-6 seconds (296 bytes allocated)

Beaucoup mieux. Pourquoi ne pas [:]sub? Je ne sais pas. Eh bien, j'ai en quelque sorte de faire. Quand vous allez à l'index z[10] Julia pense, mmdp, z est comme x, à l'exception de l'index sont compensés par 0 donc z[10]x[10+0]. Là vous allez. Ce petit ajout supplémentaire vous coûtera à long terme si vous faites beaucoup de l'indexation. Pour réparer cela vous avez besoin un concept comme pointeurs qui est contre la religion de Julia.

mise à Jour Julia désapprouve maintenant [:] (la version 0.4.0)

julia> @time x=[1:10000];
WARNING: [a] concatenation is deprecated; use collect(a) instead
in depwarn at deprecated.jl:73
in oldstyle_vcat_warning at ./abstractarray.jl:29
in vect at abstractarray.jl:32
while loading no file, in expression starting on line 155
0.530051 seconds (180.12 k allocations: 9.429 MB, 5.26% gc time)

julia> @time x=[1:10000];
WARNING: [a] concatenation is deprecated; use collect(a) instead
in depwarn at deprecated.jl:73
in oldstyle_vcat_warning at ./abstractarray.jl:29
in vect at abstractarray.jl:32
while loading no file, in expression starting on line 155
0.001373 seconds (303 allocations: 714.656 KB)

recueillir est plus rapide

julia> @ time x=collect(1:10000);
0.003991 seconds (35 allocations: 80.078 KB)

julia> @ time x=collect(1:10000);
0.000031 seconds (8 allocations: 78.406 KB)

comparable à des sous-tableaux

julia> @time z = sub(x,1:10000);
0.067002 seconds (36.27 k allocations: 1.792 MB)

julia> @time z = sub(x,1:10000);
0.000016 seconds (7 allocations: 288 bytes)
3
répondu Michael Fox 2016-03-08 22:36:15
la source

Autres questions sur