IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Voir le flux RSS

danielhagnoul

Julia. Comment éviter les variables globales ?

Noter ce billet
par , 26/01/2021 à 22h16 (7264 Affichages)
  • Le 2021-01-26, j'utilise Julia_1.5.3 sur VS_Code_1.52.1. Ordinateur : W10 Pro, i9-10900F.
  • Préalables, mes billets précédents sur Julia sont supposés connus et assimilés.


Citation Envoyé par Traduction Google
Une variable globale peut avoir sa valeur, et donc son type, changer à tout moment. Cela rend difficile pour le compilateur d'optimiser le code à l'aide de variables globales. Les variables doivent être locales ou passées comme arguments aux fonctions, dans la mesure du possible.

Tout code critique pour les performances ou en cours de benchmark doit être à l'intérieur d'une fonction.
Voir : https://docs.julialang.org/en/v1/man...formance-tips/

Différence dans le temps d'exécution lorsque le code est dans une fonction :

Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
texte = "Par une belle nuit d'été..."
liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
@time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
@time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
# P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
 
function main()
    texte = "Par une belle nuit d'été..."
    liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
    @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
    # P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
end
 
main()
 
#=
Le premier temps est pollué par le temps de compilation
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.210999 seconds (645.15 k allocations: 33.800 MiB)
 
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.022334 seconds (44.84 k allocations: 2.294 MiB, 21.29% gc time)
 
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.000164 seconds (96 allocations: 3.891 KiB)
=#

Différence dans le temps d'exécution lorsque le code est dans une portée locale :

Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
texte = "Par une belle nuit d'été..."
liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
@time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
@time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
# P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
 
let
    texte = "Par une belle nuit d'été..."
    liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
    @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
    # P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
end
 
#=
Le premier temps est pollué par le temps de compilation
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.221659 seconds (645.15 k allocations: 33.800 MiB)
 
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.026124 seconds (44.84 k allocations: 2.294 MiB, 19.41% gc time)
  
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.017637 seconds (44.84 k allocations: 2.294 MiB)  
=#

Le plus rapide, c'est le code dans une fonction : 0.000164 seconde
Le code dans une portée locale (0.017637 seconde) est 107.5 fois plus lent.
Le code avec des variables globales (0.026124 seconde) est 159,3 fois plus lent.

Voyons la performance lorsque les variables sont incluses dans un module.

Dans le premier module, elles sont globales contrairement à ce que je pensais encore ces derniers jours.
Dans le deuxième module, elles sont locales et la fonction est globale pour pouvoir être appelée de l'extérieur du module.
Dans le troisième module, elles sont incluses dans la fonction.

Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
module dvjhTest1
    texte = "Par une belle nuit d'été..."
    liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
    function f_dvjhTest1()
        @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
        @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
    end
end
 
module dvjhTest2
    let
        texte = "Par une belle nuit d'été..."
        liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
 
        global function f_dvjhTest2()
            @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
        end
    end
end
 
module dvjhTest3
    function f_dvjhTest3()
        texte = "Par une belle nuit d'été..."
        liste = ["1", "2", "3", "4", "5", "4", "3", "2"]
        @time join([t[1] * t[2] for t in collect(zip(texte, Iterators.cycle(liste)))]) |> println
    end
end
 
# Appel des modules contenus dans ce fichier
using .dvjhTest1, .dvjhTest2, .dvjhTest3
 
function main()
    dvjhTest1.f_dvjhTest1()
    dvjhTest2.f_dvjhTest2()
    dvjhTest3.f_dvjhTest3()
end
 
main()
 
#=
Le premier temps est pollué par le temps de compilation
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.175639 seconds (431.01 k allocations: 22.826 MiB)
 
Variables globales
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.016556 seconds (44.47 k allocations: 2.269 MiB)   
 
Variables locales
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.000123 seconds (96 allocations: 3.891 KiB)        
 
Variables dans la fonction
P1a2r3 4u5n4e3 2b1e2l3l4e5 4n3u2i1t2 3d4'5é4t3é2.1.2.3
  0.000096 seconds (96 allocations: 3.891 KiB)    
=#

Le plus rapide, c'est le code dans une fonction : 0.000096 seconde
Le code dans une portée locale (0.000123 seconde) est 1,28 fois plus lent.
Le code avec des variables globales (0.016556 seconde) est 172,45 fois plus lent.

On remarquera que :
  1. dans un module, les différences de performance entre la fonction et la portée locale sont resserrées.
  2. l'utilisation de la portée locale permet d'avoir des fonctions globales et des fonctions privées.
  3. même si l'on n'exporte pas la fonction dans le module, elle est accessible par "nom_module.nom_fonction".

Comment éviter les variables globales ?

Il faut les mettre dans une fonction ou, moins performant, dans une portée locale créée avec let.

Licence Creative Commons Attribution 2.0 Belgique

Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Viadeo Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Twitter Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Google Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Facebook Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Digg Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Delicious Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog MySpace Envoyer le billet « Julia. Comment éviter les variables globales ? » dans le blog Yahoo

Mis à jour 26/01/2021 à 22h34 par danielhagnoul

Catégories
Programmation , Julia

Commentaires