Optimisation de calculs, appel à contributions

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

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 16 Mar 2016, 08:20

Bonjour à tous,

Dans le cadre d'une formation je souhaite montrer que pour résoudre un même problème différentes possibilités s'offrent à nous, avec plus ou moins d'efficacité. Pour ça je pars d'un data.frame 1000 * 1000, avec pour but de calculer la moyenne de chacune des colonnes.

Les objectifs sont de montrer :
1. quelques possibilités avec des fonctions de bases et des fonctions importées de différentes librairies
2. que bien programmer ou bien choisir sa fonction à un impact sur le temps de calcul.
3. que la nature de l'objet sur lequel on travaille est importante

J'ai commencé à recenser plusieurs façons de faire, avec des boucles, des fonctions de bases de type lapply et des fonctions faisant appel à des librairies souvent réputées pour être efficaces (plyr, dplyr). Après il y a surement des tas de librairie que je ne connais pas qui propose ce genre de calculs.

Est-ce que vous verriez d'autres possibilités ? Des plus efficaces ? Ou des exemples de ce qui ne faut vraiment pas faire (summarise_each et apply sont de mauvais élèves ;-))

Code : Tout sélectionner

require(microbenchmark)
require(plyr)
require(dplyr)
require(data.table)
require(matrixStats)
require(iterators)

set.seed(100)
tab <- as.data.frame(matrix(rnorm(1e6), 1e3))
tab2 <- as.matrix(tab)
tab3 <- as.data.table(tab)

nr <- nrow(tab)
nc <- ncol(tab)

f <- function(x) .Internal(mean(x))
f2 <- function(x) sum(x)/length(x)

auxi <- names(tab)
auxi <- sprintf("%s = sum(%s)", auxi, auxi)
auxi <- paste(auxi, collapse=",")
auxi <- paste("summarise(tab,", auxi, ")", sep="")
auxi <- parse(text=auxi)

res <- microbenchmark(
  Lapply = res <- unlist(lapply(tab, mean)),
  Lapply2 = res <- unlist(lapply(tab, f)),
  Lapply3 = res <- unlist(lapply(tab, f2)),
  Lapply4 = res <- unlist(lapply(tab, sum))/nr,
  Lapply5 = res <- unlist(lapply(tab, sum))/nrow(tab),
  Sapply = res <- sapply(tab, mean),
  Sapply2 = res <- sapply(tab, f),
  Sapply3 = res <- sapply(tab, f2),
  Sapply4 = res <- sapply(tab, sum)/nr,
  Sapply5 = res <- sapply(tab, sum)/nrow(tab),
  Apply = res <- apply(tab, 2, mean),
  Apply2 = res <- apply(tab, 2, f),
  Apply3 = res <- apply(tab, 2, f2),
  Apply4 = res <- apply(tab, 2, sum)/nr,
  Apply5 = res <- apply(tab, 2, sum)/nrow(tab),
  Apply.2 = res <- apply(tab, 2, mean),
  Apply2.2 = res <- apply(tab2, 2, f),
  Apply3.2 = res <- apply(tab2, 2, f2),
  Apply4.2 = res <- apply(tab2, 2, sum)/nr,
  Apply5.2 = res <- apply(tab2, 2, sum)/nrow(tab2),
  Vapply = {res <- vapply(seq_along(tab),
                          function(x) mean(tab[[x]]), numeric(1))},
  Vapply2 = {res <- vapply(seq_along(tab),
                           function(x) f(tab[[x]]), numeric(1))},
  Vapply3 = {res <- vapply(seq_along(tab),
                           function(x) f2(tab[[x]]), numeric(1))},
  Vapply4 = {res <- vapply(seq_along(tab),
                           function(x) sum(tab[[x]]), numeric(1))/nr},
  Vapply5 = {res <- vapply(seq_along(tab),
                           function(x) sum(tab[[x]]), numeric(1))/nrow(tab)},
  Rowsums = res <- rowsum(tab, group = gl(1, nrow(tab)))/nrow(tab),
  ColMeans = res <- colMeans(tab),
  colMeans2 = res <- colMeans(tab2),
  colMeans3 = res <- .colMeans(tab2, nr, nc),
  For = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- mean(tab[[i]])
    }
  },
  For2 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- f(tab[[i]])
    }
  },
  For3 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- f2(tab[[i]])
    }
  },
  For4 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])/length(tab[[i]])
    }
  },
  For5 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])
    }
    res <- res/nr
  },
  For6 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])
    }
    res <- res/nrow(tab)
  },
  weightedMeans = {
    ws <- vector("numeric", nr)+1
    ws <- ws/nr               
    res <- colWeightedMeans(tab, ws)
  },
  weightedMeans2 = {
    ws <- vector("numeric", nr)+1
    ws <- ws/nr               
    res <- colWeightedMeans(tab2, ws)
  },
  Diag = res <- diag(t(tab2) %*% matrix(1, nr, nc))/nr,
  Diag2 = res <- diag(crossprod(tab2, matrix(1, nr, nc))),
  Dplyr = res <- summarise_each(tab, funs(mean)),
  Dplyr2 = res <- summarise_each(tab, funs(f)),
  Dplyr3 = res <- summarise_each(tab, funs(f2)),
  Dplyr4 = res <- summarise_each(tab, funs(sum))/nr,
  Dplyr5 = res <- summarise_each(tab, funs(sum))/nrow(tab),
  Dplyr6 = res <- eval(auxi),
  Dplyr7 = {
    auxi <- names(tab)
    auxi <- sprintf("%s = sum(%s)", auxi, auxi)
    auxi <- paste(auxi, sep=",")
    auxi <- paste("summarise(tab,", auxi, ")", sep="")
    auxi <- parse(text=auxi)
    res <- eval(auxi)
  },
  Plyr = res <- colwise(mean)(tab),
  Plyr2 = res <- colwise(f)(tab),
  Plyr3 = res <- colwise(f2)(tab),
  Plyr4 = res <- colwise(sum)(tab)/nr,
  Plyr5 = res <- colwise(sum)(tab)/nrow(tab),
  Data.table = res <- tab3[, lapply(.SD, mean)],
  Data.table2 = res <- tab3[, lapply(.SD, f)],
  Data.table3 = res <- tab3[, lapply(.SD, f2)],
  Data.table4 = res <- tab3[, lapply(.SD, sum)]/nr,
  Data.table5 = res <- tab3[, lapply(.SD, sum)]/nrow(tab)
)


Cordialement,
Maxime

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Re: Optimisation de calculs, appel à contributions

Messagepar Eric Wajnberg » 16 Mar 2016, 12:40

Coder en C, et utiliser .C(). C'est ce que je fais quand j'ai besoin de truc très rapides.

HTH, Eric.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 16 Mar 2016, 13:26

Le but n'est pas de programmer dans un autre langage mais de rester dans R. Si tu sais faire ça avec Rcpp alors ça m'intéresse.
Maxime

Eric Wajnberg
Messages : 776
Enregistré le : 11 Aoû 2008, 15:37
Contact :

Re: Optimisation de calculs, appel à contributions

Messagepar Eric Wajnberg » 16 Mar 2016, 13:30

Logez Maxime a écrit :Si tu sais faire ça avec Rcpp alors ça m'intéresse.Maxime

Non, désolé, je n'utilises pas Rcpp.

Eric.

Bastien Gamboa
Messages : 151
Enregistré le : 13 Jan 2011, 21:31

Re: Optimisation de calculs, appel à contributions

Messagepar Bastien Gamboa » 17 Mar 2016, 08:24

Bonjour,

Deux pistes non testées :
1/ Compiler les fonctions (http://www.r-statistics.com/2012/04/speed-up-your-r-code-using-a-just-in-time-jit-compiler/)

Code : Tout sélectionner

require(compiler)
g <- cmpfun(f)

2/ Additionner les valeurs à la place de faire la somme, puis tout diviser par 'nr'

Code : Tout sélectionner

f <- function(x) Reduce("+",x)/nr

Le retour des simulations pourraient être très intéressant à poster ici.

HTH,
Bastien

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 17 Mar 2016, 09:33

Bonjour,

Merci pour cette contribution, je ne manquerais pas de l'intégrer aux possibilités.

Cordialement,
Maxime

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 17 Mar 2016, 11:24

re,

un premier retrour rapide, compiler une fonction qui fait appelle à du code interne, n'amène rien de plus. Le cmpfun de f ne modifie rien.

Cordialement,
Maxime

Alexandre Dangléant
Messages : 270
Enregistré le : 30 Mar 2010, 14:38

Re: Optimisation de calculs, appel à contributions

Messagepar Alexandre Dangléant » 29 Mar 2016, 08:43

Bonjour,

Je n'ai pas grand-chose à t'apporter mais je suis intéressé par une formation sur ce sujet. Je m'oriente vers le développement d'appli avec Shiny et avoir de bonnes notions sur ces aspects me semble important pour diminuer au maximum les temps de réponse des appli. Vu qu'avant de lire ton post j'étais persuadé que les "apply" étaient des fonctions optimisées...

C'est une formation interne ou ouverte?

A+

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 29 Mar 2016, 19:13

Bonjour,

Toute contribution est la bienvenue. Les objectifs sont de :
- montrer que l'on peut utiliser des fonctions et ou méthodes très différentes pour arriver au même résultat
- que selon la fonction/méthode le temps de calcul sera plus ou moins loin.
Pour ce qui est de la formation, ce n'est pas une formation a proprement dite sur l'optimisation. Ces exemples serviront juste pour un rapide exemple. Sinon il s'agit de la formation des statistiques sous R proposée par ECCOREV. Les inscriptions sont déjà closes.

Voici une version mise à jour et les résultats qui vont avec.

Code : Tout sélectionner

require(microbenchmark)
require(plyr)
require(dplyr)
require(data.table)
require(matrixStats)
require(foreach)
require(iterators)
require(doSNOW)

set.seed(100)
tab <- as.data.frame(matrix(rnorm(1e6), 1e3))
tab2 <- as.matrix(tab)
tab3 <- as.data.table(tab)

nr <- nrow(tab)
nc <- ncol(tab)

f <- function(x) .Internal(mean(x))
f2 <- function(x) sum(x)/length(x)

auxi <- names(tab)
auxi <- sprintf("%s = sum(%s)", auxi, auxi)
auxi <- paste(auxi, collapse=",")
auxi <- paste("summarise(tab,", auxi, ")", sep="")
auxi <- parse(text=auxi)

cl <- makeCluster(c("localhost","localhost"), type = "SOCK")
clusterExport(cl, c("tab", "f"))
registerDoSNOW(cl)

mic <- microbenchmark(
  Lapply = res <- unlist(lapply(tab, mean)),
  Lapply2 = res <- unlist(lapply(tab, f)),
  Lapply3 = res <- unlist(lapply(tab, f2)),
  Lapply4 = res <- unlist(lapply(tab, sum))/nr,
  Lapply5 = res <- unlist(lapply(tab, sum))/nrow(tab),
  Sapply = res <- sapply(tab, mean),
  Sapply2 = res <- sapply(tab, f),
  Sapply3 = res <- sapply(tab, f2),
  Sapply4 = res <- sapply(tab, sum)/nr,
  Sapply5 = res <- sapply(tab, sum)/nrow(tab),
  Apply = res <- apply(tab, 2, mean),
  Apply2 = res <- apply(tab, 2, f),
  Apply3 = res <- apply(tab, 2, f2),
  Apply4 = res <- apply(tab, 2, sum)/nr,
  Apply5 = res <- apply(tab, 2, sum)/nrow(tab),
  Apply.2 = res <- apply(tab, 2, mean),
  Apply2.2 = res <- apply(tab2, 2, f),
  Apply3.2 = res <- apply(tab2, 2, f2),
  Apply4.2 = res <- apply(tab2, 2, sum)/nr,
  Apply5.2 = res <- apply(tab2, 2, sum)/nrow(tab2),
  Vapply = {res <- vapply(seq_along(tab),
                          function(x) mean(tab[[x]]), numeric(1))},
  Vapply2 = {res <- vapply(seq_along(tab),
                           function(x) f(tab[[x]]), numeric(1))},
  Vapply3 = {res <- vapply(seq_along(tab),
                           function(x) f2(tab[[x]]), numeric(1))},
  Vapply4 = {res <- vapply(seq_along(tab),
                           function(x) sum(tab[[x]]), numeric(1))/nr},
  Vapply5 = {res <- vapply(seq_along(tab),
                           function(x) sum(tab[[x]]), numeric(1))/nrow(tab)},
  Rowsums = res <- rowsum(tab, group = gl(1, nrow(tab)))/nrow(tab),
  ColMeans = res <- colMeans(tab),
  colMeans2 = res <- colMeans(tab2),
  colMeans3 = res <- .colMeans(tab2, nr, nc),
  colMeans4 = res <- Matrix:::colMeans(tab),
  colMeans5 = res <- Matrix:::colMeans(tab2),
  colMeans6 = res <- Matrix:::colMeans(tab3),
  For = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- mean(tab[[i]])
    }
  },
  For2 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- f(tab[[i]])
    }
  },
  For3 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- f2(tab[[i]])
    }
  },
  For4 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])/length(tab[[i]])
    }
  },
  For5 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])
    }
    res <- res/nr
  },
  For6 = {
    res <- vector("numeric", ncol(tab))
    for (i in seq_along(res)) {
      res[i] <- sum(tab[[i]])
    }
    res <- res/nrow(tab)
  },
  weightedMeans = {
    ws <- vector("numeric", nr)+1
    ws <- ws/nr               
    res <- colWeightedMeans(tab, ws)
  },
  weightedMeans2 = {
    ws <- vector("numeric", nr)+1
    ws <- ws/nr               
    res <- colWeightedMeans(tab2, ws)
  },
  Diag = res <- diag(t(tab2) %*% matrix(1, nr, nc))/nr,
  Diag2 = res <- diag(crossprod(tab2, matrix(1, nr, nc))),
  Dplyr = res <- summarise_each(tab, funs(mean)),
  Dplyr2 = res <- summarise_each(tab, funs(f)),
  Dplyr3 = res <- summarise_each(tab, funs(f2)),
  Dplyr4 = res <- summarise_each(tab, funs(sum))/nr,
  Dplyr5 = res <- summarise_each(tab, funs(sum))/nrow(tab),
  Dplyr = res <- summarise_each(tab3, funs(mean)),
  Dplyr2.2 = res <- summarise_each(tab3, funs(f)),
  Dplyr3.2 = res <- summarise_each(tab3, funs(f2)),
  Dplyr4.2 = res <- summarise_each(tab3, funs(sum))/nr,
  Dplyr5.2 = res <- summarise_each(tab3, funs(sum))/nrow(tab),
  Plyr = res <- colwise(mean)(tab),
  Plyr2 = res <- colwise(f)(tab),
  Plyr3 = res <- colwise(f2)(tab),
  Plyr4 = res <- colwise(sum)(tab)/nr,
  Plyr5 = res <- colwise(sum)(tab)/nrow(tab),
  Plyr.2 = res <- numcolwise(mean)(tab),
  Plyr2.2 = res <- numcolwise(f)(tab),
  Plyr3.2 = res <- numcolwise(f2)(tab),
  Plyr4.2 = res <- numcolwise(sum)(tab)/nr,
  Plyr5.2 = res <- numcolwise(sum)(tab)/nrow(tab), 
  Data.table = res <- tab3[, lapply(.SD, mean)],
  Data.table2 = res <- tab3[, lapply(.SD, f)],
  Data.table3 = res <- tab3[, lapply(.SD, f2)],
  Data.table4 = res <- tab3[, lapply(.SD, sum)]/nr,
  Data.table5 = res <- tab3[, lapply(.SD, sum)]/nrow(tab),
  Map = res <- unlist(Map(mean, tab)),
  Map2 = res <- unlist(Map(f, tab)),
  Map3 = res <- unlist(Map(f2, tab)),
  Map4 = res <- unlist(Map(sum, tab))/nr,
  Map5 = res <- unlist(Map(sum, tab))/nrow(tab),
  Foreach = res <- foreach(i = seq_along(tab), .combine='c') %do% f(tab[[i]]),
  Foreach2 = res <- foreach(i = iter(tab, by='col'), .combine='c') %do% f(i),
  Foreach3 = res <- foreach(i = iter(tab, by='col'), .combine='c') %do% f(i),
  ParLapply = res <- unlist(parLapply(cl, seq_along(tab), function(x) f(tab[[x]]))),
  ParSapply = res <- parSapply(cl, seq_along(tab), function(x) f(tab[[x]])),
  Foreachpar = res <- foreach(i = seq_along(tab), .combine='c') %dopar% f(tab[[i]])
)


Code : Tout sélectionner

colMeans3         1.21    1.17
colMeans2         1.23    1.19
colMeans5         1.28    1.24
Lapply4           2.59    2.48
Lapply5           2.59    2.49
Sapply4           2.63    2.51
Sapply5           2.66    2.58
Lapply3           3.38    3.18
Sapply3           3.41    3.20
weightedMeans2    4.15    3.56
Lapply2           4.02    3.82
Sapply2           4.01    3.91
Plyr3.2           6.29    5.74
Plyr3             6.35    5.98
Plyr2.2           6.96    6.47
Plyr2             7.02    6.60
Sapply            8.29    7.87
Lapply            8.57    7.89
ParLapply         9.77    8.06
Map5              9.17    8.56
Map4              9.34    8.62
ParSapply        10.42    8.86
Vapply4           9.96    8.99
Vapply5           9.76    9.13
Map3             10.39    9.47
For5             10.39    9.79
For6             10.82    9.88
Map2             10.63    9.91
Vapply3          11.20    9.99
ColMeans         10.51   10.28
colMeans4        22.84   10.43
Plyr.2           11.33   10.58
Vapply2          11.58   10.64
Plyr             11.69   10.81
For3             11.93   10.82
colMeans6        13.69   11.27
For2             12.43   11.55
Map              16.73   15.66
Vapply           16.97   15.77
For              17.86   17.07
For4             19.13   17.63
Apply4.2         23.73   22.14
Apply5.2         24.44   23.77
Apply2.2         25.28   25.85
Apply3.2         24.44   26.70
Apply4           38.29   33.91
Apply3           34.52   34.40
Apply5           38.28   34.57
Apply2           36.30   35.23
Apply.2          47.08   39.87
Apply            42.99   40.18
Data.table3      69.13   67.58
Data.table2      70.43   69.04
Data.table       76.05   72.87
Rowsums          82.62   80.72
Plyr4            82.43   80.95
Plyr5            83.39   81.44
Plyr4.2          86.17   81.52
Plyr5.2          87.52   81.61
weightedMeans   165.06  152.64
Data.table5     181.84  175.46
Data.table4     181.77  177.58
Dplyr           191.92  200.70
Dplyr2.2        221.22  213.61
Dplyr3.2        222.19  215.51
Dplyr4          246.77  232.81
Dplyr5          237.54  233.94
Dplyr2          295.03  283.19
Dplyr3          288.12  283.22
Foreach         327.95  319.09
Dplyr5.2        326.15  319.31
Dplyr4.2        327.18  322.09
Foreach3        335.24  324.79
Foreach2        335.22  327.29
Foreachpar      645.84  625.38
Diag            769.42  754.46
Diag2          1210.49 1205.29

Il faut bien voir que ceci n'est vrai que dans ce cas là et avec mon ordinateur. Avec moins de lignes et/ou moins de colonne, l'efficacité de certaines fonctions peut changer (et donc le rang des réponses).
Néanmoins quelques résultats (certains à priori triviaux) :
- utiliser une fonction qui fait appel à une fonction interne (.mean) s'avère beaucoup plus efficace. Par contre on perd tous les contrôles préalables que l'on a dans la fonction mean.
- le lapply s'en sort toujours bien (coupler avec unlist et tab[[i]] au lieu de tab[,i])
- le apply est super lent
- colMeans est la fonction la plus rapide si tant est qu'on travaille sur une matrice
- le as.matrix de la fonction colMeans est super couteux en temps ici
- la fonction summarise_each du package dplyr n'est pas efficace, préférer colwise de la librairie plyr qui s'en sort bien
- la parallélisation c'est bien mais c'est couteux en temps (création de cluster, transfert de données, execution ...) donc il faut l'utiliser à bon escient. Ici le calcul en lui même est tellement rapide que la parallélisation n'apporte pas grand chose (n=2 cores). On voit aussi que selon la fonction utiliser pour la parallélisation, parLapply ou foreach les résultats ne sont pas du tout les mêmes en terme d'efficacité.
- quand on fait une boucle faire attention à ne pas répéter des opérations à chaque itération qui pourraient être réalisées en dehors (/nrow(tab))
- la boucle ne s'en sort pas si mal et est loin d'être à éviter (faut juste bien la programmer et ne pas les multiplier)

Cordialement,
Maxime

Alexandre Dangléant
Messages : 270
Enregistré le : 30 Mar 2010, 14:38

Re: Optimisation de calculs, appel à contributions

Messagepar Alexandre Dangléant » 30 Mar 2016, 08:40

Merci Maxime pour ce partage.

Pierre Bady
Messages : 405
Enregistré le : 02 Mai 2006, 07:46

Re: Optimisation de calculs, appel à contributions

Messagepar Pierre Bady » 30 Mar 2016, 13:46

Hello,

la version de la librairie BLAS utilisée (e.g. openblas, MKL) a aussi une incidence sur le calcul matriciel. Sur certaines opérations, ça fait des grosses différences (viewtopic.php?f=3&t=7023&p=32742#p32742).

bon, j'avoue qu'un truc qui tourne pas trop vite, c'est cool aussi ... ça permet de réfléchir et de se prendre un café :D
c'est peut-être un élément à prendre en compte, non? :P

@++ et bonne journée,

pierre
=@===--------¬-------¬------¬-----¬
liens utiles :
http://www.gnurou.org/Writing/SmartQuestionsFr
http://neogrifter.free.fr/welcomeOnInternet.jpg
]<((((*< -------------------------------

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 30 Mar 2016, 14:35

Salut Pierre,

Comme tu le sais déjà j'ai pas mal amélioré mes temps de calculs, pour tout ce qui est à base de calculs matriciels (lm, etc.) en utilisant la version de R fourni par Révolution Analytics : Revolution R Open. Les calculs matriciels sont parallélisées sans qu'on n'est rien à faire :-).

C'est sur que de laisser tourner un code pour aller boire un café c'est parfois assez sympa, dommage que tu sois trop loin :-(

@+
Max

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 04 Avr 2016, 11:17

re,

Deux autres possibilités qui rabattent un peu les cartes :

Code : Tout sélectionner

 res <- vector("numeric", ncol(tab))
    u <- 1
    for (i in tab) {
      res[[u]] <- sum(i)
      u <- u+1
    }
    res <- res/nrow(tab)
    #ou
    res <- vapply(tab, sum, numeric(1))
    res <- res/nrow(tab)

Les résultats avec ces deux nouvelles possibilités :

Code : Tout sélectionner

                      Mean      Median
Lapply            8.803776    8.248587
Lapply2           4.112923    3.909398
Lapply3           3.601539    3.310469
Lapply4           2.752009    2.596501
Lapply5           2.873501    2.622160
Sapply            9.507656    8.645022
Sapply2           4.421950    4.182669
Sapply3           3.842415    3.400276
Sapply4           2.891210    2.685453
Sapply5           2.786507    2.667491
Apply            49.142816   45.234440
Apply2           44.234085   39.849851
Apply3           38.625521   37.907876
Apply4           42.577072   37.933749
Apply5           41.196884   39.317850
Apply.2          46.256717   44.256396
Apply2.2         26.855210   27.980962
Apply3.2         26.156381   27.523159
Apply4.2         26.114479   26.519026
Apply5.2         26.527238   28.010469
Vapply           18.348658   17.133523
Vapply2          12.400665   11.156633
Vapply3          11.991537   11.216504
Vapply4          11.395191    9.666046
Vapply5          11.040132    9.874741
Vapply6           2.247163    2.092938
Rowsums          91.602056   88.246578
ColMeans         12.778006   11.764757
colMeans2         1.285494    1.239342
colMeans3         1.281277    1.231858
colMeans4        25.394610   11.824414
colMeans5         1.378479    1.303703
colMeans6        13.186449   12.558482
For              20.576431   18.886689
For2             13.603052   12.299752
For3             13.474436   11.741236
For4             20.935767   19.425534
For5             13.224292   10.947724
For6             12.158318   10.643449
For7              3.829713    3.521088
weightedMeans   180.004534  164.731605
weightedMeans2    5.141131    5.194497
Diag            854.122793  826.819240
Diag2          1298.477968 1265.681638
Dplyr           176.646951  167.085839
Dplyr2          324.098241  307.526279
Dplyr3          322.621921  305.457505
Dplyr4          269.865593  255.631132
Dplyr5          260.902111  251.628720
Dplyr.2         235.882114  231.674608
Dplyr2.2        235.078890  228.878393
Dplyr3.2        236.926153  229.282312
Dplyr4.2        358.317859  345.214127
Dplyr5.2        355.676652  341.107368
Plyr             12.846768   11.755562
Plyr2             7.711193    7.095205
Plyr3             6.967559    6.374180
Plyr4            95.779194   90.270663
Plyr5            98.338031   91.229890
Plyr.2           12.304447   11.285998
Plyr2.2           7.391911    6.861279
Plyr3.2           8.111700    6.394708
Plyr4.2          94.055078   89.547500
Plyr5.2          94.810871   89.400601
Data.table       82.908115   79.027430
Data.table2      78.034051   74.478690
Data.table3      74.495237   71.226811
Data.table4     201.772609  193.392536
Data.table5     200.618970  190.623050
Map              17.528457   16.354979
Map2             12.020092   10.881865
Map3             11.370657    9.969466
Map4             11.645668    9.326489
Map5             10.634630    9.495625
Foreach         369.018103  350.048112
Foreach2        375.474307  360.603677
Foreach3        385.397449  354.283808
ParLapply        10.349496    8.843881
ParSapply        10.862848    9.732117
Foreachpar      703.775957  676.581251


et les 10 plus efficaces :

Code : Tout sélectionner

              Mean   Median
colMeans3 1.281277 1.231858
colMeans2 1.285494 1.239342
colMeans5 1.378479 1.303703
Vapply6   2.247163 2.092938
Lapply4   2.752009 2.596501
Sapply5   2.786507 2.667491
Lapply5   2.873501 2.622160
Sapply4   2.891210 2.685453
Lapply3   3.601539 3.310469
For7      3.829713 3.521088
et les 10 plus lents :

Code : Tout sélectionner

Dplyr3          322.621921  305.457505
Dplyr2          324.098241  307.526279
Dplyr5.2        355.676652  341.107368
Dplyr4.2        358.317859  345.214127
Foreach         369.018103  350.048112
Foreach2        375.474307  360.603677
Foreach3        385.397449  354.283808
Foreachpar      703.775957  676.581251
Diag            854.122793  826.819240
Diag2          1298.477968 1265.681638

Comme quoi bien programmée la boucle c'est quand même bien et que le vapply est plus efficace que la boucle et que les autres fonctions de la famille des apply.

Cordialement,
Maxime

Alexandre Dangléant
Messages : 270
Enregistré le : 30 Mar 2010, 14:38

Re: Optimisation de calculs, appel à contributions

Messagepar Alexandre Dangléant » 08 Avr 2016, 16:33

Salut,

Je m'aperçois maintenant que tu n'as pas inclus aggregate dans tes tests. Je sais que tu pars sur un calcul simple de moyenne par colonne, mais comme cette fonction est très couramment utilisée tu as peut être déjà un avis sur la question?

Ou peut être que tes tests répondent déjà à cette question. Par exemple, aggregate fait peut être appel à apply et tapply, auquel cas on peut considérer qu'elle ne sera pas très performante, et que dans certains cas il vaut mieux passer par deux sapply pour laquelle tu as montré de bonnes performances.

Merci d'avance pour ta réponse.

Cordialement.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Optimisation de calculs, appel à contributions

Messagepar Logez Maxime » 11 Avr 2016, 19:15

Bonjour,

en fait aggregate est un lapply de lapply. J'envisage aussi de faire des tests pour les agrégations de tableau par rapport à un ou deux facteurs. Je mettrais ça aussi plus tard quand j'aurai un peu de temps :-)

Cordialement,
Maxime


Retourner vers « Questions en cours »

Qui est en ligne

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