gganimate en multicore

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

gganimate en multicore

Messagepar Jean-Emmanuel Longueville » 21 Fév 2022, 12:25

Bonjour,
Je cherche à faire un graphique en vidéos avec gganimate.
Mes graphiques sont très nombreux > 100 000.
Du coup j'aurais voulu profiter des 15 coeurs disponibles de mon processeurs.
J'ai installé cette version de gganimate : https://github.com/HenrikBengtsson/gganimate/tree/feature/parallel-animate
Trouvé via cette pull request : https://github.com/thomasp85/gganimate/pull/403
Et cette intervention stack overflow : https://stackoverflow.com/questions/67321487/how-to-use-multiple-cores-to-make-gganimate-faster

Cependant je ne vois pas de différence d'usage des proc.

Du coup ma question est comment peut on faire tourner du code R en multicoeur ?
merci
Si cela peut aider voici un test :

Code : Tout sélectionner


future
::plan("sequential"## default
t0 <- system.time(data_gx %>%
    
group_by(RFID) %>%
    
left_join(., x_id) %>%
    
mutate(event case_when(nature == "Intellicage" val_xIC[x_id],
                             
nature == "Main" val_xMn[x_id],
t0 <- system.time(data_gx %>%
+     
group_by(RFID) %>%
+     
left_join(., x_id) %>%
+     
mutate(event case_when(nature == "Intellicage" val_xIC[x_id],
+                              
nature == "Main" val_xMn[x_id],
+                              
nature == "Wheels" val_xRw[x_id]),
+            
date_hm format(date_event"%F %H:%M"),
+            
date_h format(date_event"%F %H"),
+            
date_j format(date_event"%Y-%m-%d"),
+            
ytraitement case_when(traitement == "coc" 0.3,
+                                    
traitement == "sal" 0.8))
+ )

future::plan("multicore"workers 4L)
t1 <- system.time(data_gx %>%
    
group_by(RFID) %>%
    
left_join(., x_id) %>%
    
mutate(event case_when(nature == "Intellicage" val_xIC[x_id],
                             
nature == "Main" val_xMn[x_id],
                             
nature == "Wheels" val_xRw[x_id]),
           
date_hm format(date_event"%F %H:%M"),
           
date_h format(date_event"%F %H"),
           
date_j format(date_event"%Y-%m-%d"),
           
ytraitement case_when(traitement == "coc" 0.3,
                                   
traitement == "sal" 0.8))
)
Joiningby "RFID"

future::plan("multicore"workers 4L)
t1 <- system.time(data_gx %>%
+     
group_by(RFID) %>%
+     
left_join(., x_id) %>%
+     
mutate(event case_when(nature == "Intellicage" val_xIC[x_id],
+                              
nature == "Main" val_xMn[x_id],
+                              
nature == "Wheels" val_xRw[x_id]),
+            
date_hm format(date_event"%F %H:%M"),
+            
date_h format(date_event"%F %H"),
+            
date_j format(date_event"%Y-%m-%d"),
+            
ytraitement case_when(traitement == "coc" 0.3,
+                                    
traitement == "sal" 0.8))
+ )
Joiningby "RFID"
> print(t0 t1)
utilisateur     système      écoulé 
  1.0768970   0.8314108   1.0692858 
length(data_gx)
[
18
nrow(data_gx)
[
136518393
Jean-Emmanuel
Ingénieur d'étude LNEC

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: gganimate en multicore

Messagepar Mickael Canouil » 22 Fév 2022, 09:43

Bonjour,

le code du test n'exploite aucune fonctions compatibles avec {future}, d'où le résultat.
"multicore" n'est pas la seule méthode de parallélisation que permet {future}, mais c'est celle de l'extension base {parallel}.

La génération de l'animation est plus rapide avec l'usage d'algorithme de rendu vidéo (`av_renderer` par exemple).

En ce qui concerne la parallèlisation dans le système {future}, le site https://www.futureverse.org/ devrait répondre à toutes vos questions.

Enfin, il est à noter que RStudio a des soucis avec {future} en "multicore".

Cordialement,
Mickaël
mickael.canouil.fr | rlille.fr

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Re: gganimate en multicore

Messagepar Jean-Emmanuel Longueville » 22 Fév 2022, 10:52

Bonjour,
Merci pour votre réponse, voici mon code exacte pour faire mon rendu, je vais continuer de creuser vos pistes :

Code : Tout sélectionner

  future::plan("multicore", workers = 15L)
  animate(gifplot, nframes = nbframe,
          #width = 1920, height = 1080,
          width = 800, height = 800,
          renderer = av_renderer(paste(gif_name, ".mp4", sep = ""),
                                codec = "libx264"))
Jean-Emmanuel
Ingénieur d'étude LNEC

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: gganimate en multicore

Messagepar Mickael Canouil » 22 Fév 2022, 13:17

Déjà, est-ce que vous avez les bons paramétrages ?

Code : Tout sélectionner

library(future)
plan("multicore", workers = 15L)
nbrOfWorkers()                    
#> [1] 15   

Chaque stratégie de parallélisation à des avantages et inconvénients (listés sur le site).
Vous pouvez essayer "multissession"

Le fork/PR de Henrik Bengtsson (développeur du "futureverse") utilise la `future_mapply` de l'extension {future.apply}.
Sous réserve, que multicore soit compatible avec la plateforme que vous utilisez, ça devrait fonctionner.
Ceci étant, d'un point de vue usage CPU, si la génération de l'image est trop rapide, cela peut ne pas se voir.

Avez-vous essayé le code de l'exemple de Henrick dans sont PR ?

Code : Tout sélectionner

library(gganimate)

anim <- ggplot(mtcarsaes(mpgdisp)) +
  
transition_states(geartransition_length 2state_length 1) +
  
enter_fade() +
  
exit_fade()

future::plan("sequential")  ## default
t0 <- system.time(animate(anim))
print(
t0)

future::plan("multisession"workers 4L# use multisession since multiprocess is deprecated
t1 <- system.time(animate(anim))
print(
t1)

print(
t0 t1)
##      user    system   elapsed 
## 2.2802385 0.9121339 2.5819751 
Mickaël
mickael.canouil.fr | rlille.fr

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Re: gganimate en multicore

Messagepar Jean-Emmanuel Longueville » 23 Fév 2022, 09:24

Oui j'ai testé le code proposé et j'ai le résultat suivant :

Code : Tout sélectionner

anim <- ggplot(mtcars, aes(mpg, disp)) +
+
     transition_states(gear, transition_length = 2, state_length = 1) +
+
     enter_fade() +
+
     exit_fade()

future::plan("sequential") ## default
t0 <- system.time(animate(anim))
print(
t0)

#   user        system      total
#   4.384615    1.360656    1.893855

future::plan("multisession", workers = 4L)
>
 
> future::plan("sequential") ## default
t1 <- system.time(animate(anim))
>
 t0 <- system.time(animate(anim))
Registered S3 methods overwritten by 'gganimate':
  method                  from                
  c
.TransmuteFactory      gganimate_parrallele
  ggplot_add
.EaseAes      gganimate_parrallele
  ggplot_add
.EnterFactory gganimate_parrallele
  ggplot_add
.ExitFactory  gganimate_parrallele
  ggplot_add
.Shadow       gganimate_parrallele
  ggplot_add
.Transition   gganimate_parrallele
  ggplot_add
.View         gganimate_parrallele
  ggplot_build
.gganim     gganimate_parrallele
  plot
.gganim             gganimate_parrallele
  print
.gganim            gganimate_parrallele
  print
.gif_image         gganimate_parrallele
  print
.sprite_image      gganimate_parrallele
  print
.video_file        gganimate_parrallele
  split
.gif_image         gganimate_parrallele
  split
.sprite_image      gganimate_parrallele
  split
.video_file        gganimate_parrallele
> print(t0)                                                                   
utilisateur     système      écoulé 
      4.827       0.135       3.827 
> 
> #   user        system      total
> #   4.384615    1.360656    1.893855
> 
> future::plan("multisession", workers = 4L)
>
 t1 <- system.time(animate(anim))
>
 #   user        system      total                                           
> #   1.30        0.61        3.58
> 
> 
> #   user        system      total
> #   4.384615    1.360656    1.893855
> 
> 
> 
> future::plan("sequential") ## default
> print(t0 / t1)
utilisateur     système      écoulé 
  0.8793952   0.9183673   0.9745353


Voici pour les paramétrages :

Code : Tout sélectionner

> library(future)
plan("multicore", workers = 15L)
>
 plan("multicore", workers = 15L)
nbrOfWorkers()
>
 nbrOfWorkers()
[
1] 15
Jean-Emmanuel
Ingénieur d'étude LNEC

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: gganimate en multicore

Messagepar Mickael Canouil » 23 Fév 2022, 13:44

Partons sur un essai plus simple, dans le code ci-dessous, multicore "perd" (il y a un gain tout de même) de façon prévisible à cause du lien entre les processus (inutile ici).

Code : Tout sélectionner

# Windows 10
library(future# v1.23.0
library(future.apply# v1.8.1

availableCores()
#> system 
#>      4

plan("sequential")
nbrOfWorkers()
#> [1] 1
nbrOfFreeWorkers()
#> [1] 1
t0 <- system.time(future_replicate(16rnorm(1e7)))

plan("multicore"workers 4L)
nbrOfWorkers()
#> [1] 4
nbrOfFreeWorkers()
#> [1] 4
t1 <- system.time(future_replicate(16rnorm(1e7)))

plan("multisession"workers 4L)
nbrOfWorkers()
#> [1] 4
nbrOfFreeWorkers()
#> [1] 4
t2 <- system.time(future_replicate(16rnorm(1e7)))

t0 t1
#>     user   system  elapsed 
#> 1.066667 1.250000 1.041872
t0 t2
#>       user     system    elapsed 
#> 11.0503597  0.2666667  1.5623269 
Mickaël
mickael.canouil.fr | rlille.fr

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Re: gganimate en multicore

Messagepar Jean-Emmanuel Longueville » 24 Fév 2022, 08:59

Voici les résultats ils sont plutôt encourageant :

Code : Tout sélectionner

# Ubuntu
library(future# v1.23.0
library(future.apply# v1.8.1

availableCores()
#> system
#>     16
plan("sequential")
nbrOfWorkers()
#> [1] 1
nbrOfFreeWorkers()
#> [1] 1
t0 <- system.time(future_replicate(16rnorm(1e7)))

plan("multicore"workers 16L)
nbrOfWorkers()
#> [1] 16
nbrOfFreeWorkers()
#> [1] 16
t1 <- system.time(future_replicate(16rnorm(1e7)))

plan("multisession"workers 16L)
nbrOfWorkers()
#> [1] 16
nbrOfFreeWorkers()
#> [1] 16
t2 <- system.time(future_replicate(16rnorm(1e7)))

t0 t1
#>     user   system  elapsed
#> 16.4205607   0.4648007   3.3217600
t0 t2
#>       user     system    elapsed
#> 15.2121212   0.5140713   3.9105004
 
Jean-Emmanuel
Ingénieur d'étude LNEC

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: gganimate en multicore

Messagepar Mickael Canouil » 24 Fév 2022, 13:28

Peut-être un soucis du fork/PR de Henrik qui est (très) en retard par rapport à la branche master.
"This branch is 2 commits ahead, 42 commits behind thomasp85:master."

J'eassaierai le code plus tard sur mon Mac.
Mickaël
mickael.canouil.fr | rlille.fr

Mickael Canouil
Messages : 1315
Enregistré le : 04 Avr 2011, 08:53
Contact :

Re: gganimate en multicore

Messagepar Mickael Canouil » 26 Fév 2022, 12:29

ça fonctionne sur MacOS (ARM).
Multicore prend trop de temps et ne devrait pas être employé pour gganimate de toutes les façons, au vu de l'implémentation de Henrik.

Code : Tout sélectionner

renv::init(bare TRUEsettings = list(use.cache FALSE))
renv::install(c(
  
"HenrikBengtsson/gganimate@feature/parallel-animate",
  
"future",
  
"future.apply"
))
#> Retrieving 'https://api.github.com/repos/HenrikBengtsson/gganimate/tarball/11edd90389fa6b51c86dd2d41a25ca5e1231ac56' ...
#>  OK [downloaded 1.2 Mb in 0.6 secs]
#> Retrieving 'https://cloud.r-project.org/bin/macosx/big-sur-arm64/contrib/4.1/future.apply_1.8.1.tgz' ...
#>  OK [file is up to date]
#> Retrieving 'https://cloud.r-project.org/bin/macosx/big-sur-arm64/contrib/4.1/future_1.24.0.tgz' ...
#>  OK [file is up to date]
#> Installing future [1.24.0] ...
#>  OK [installed binary]
#> Installing future.apply [1.8.1] ...
#>  OK [installed binary]
#> Installing gganimate [1.0.5.9000] ...
#>  OK [built from source]
library(gganimate)
#> Loading required package: ggplot2
library(future)

anim <- ggplot(mtcarsaes(mpgdisp)) +
  
transition_states(geartransition_length 2state_length 1) +
  
enter_fade() +
  
exit_fade()

availableCores()
#> system 
#>     10

plan("sequential")  ## default
t0 <- system.time(animate(anim))
print(
t0)
#>    user  system elapsed 
#>   2.822   0.598   6.600

plan("multisession"workers 10L)
t1 <- system.time(animate(anim))
print(
t1)
#>    user  system elapsed 
#>   0.523   0.063   5.392

print(t0 t1)
#>     user   system  elapsed 
#> 5.395793 9.492063 1.224036 
Mickaël
mickael.canouil.fr | rlille.fr

Jean-Emmanuel Longueville
Messages : 310
Enregistré le : 23 Fév 2011, 08:03

Re: gganimate en multicore

Messagepar Jean-Emmanuel Longueville » 28 Fév 2022, 08:50

Merci beaucoup pour ces tests
Jean-Emmanuel
Ingénieur d'étude LNEC


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité