Logez Maxime a écrit :Eric Wajnberg a écrit :Si j'ai le temps, je m'y colle, mais pas sûr que j'y arrive.. je suis en mission à l'étranger actuellement..
Après nous avoir fait saliver tu ne peux pas nous laisser sans réponse :)
Maxime
Et bien, il n'est jamais trop tard pour reprendre ce concours, et - enfin (...) - fournir une réponse correspondant à la solution que j'avais proposée.
J'ai donc re-écrit la fonction colSums() en C, avec la fonction suivante :
Code : Tout sélectionner
#include <R.h>
void colSums_eric(double *x, long *n, long *ligne, double *res)
{
int nb_ligne;
int nb_col;
int i,j;
int compteur=0;
nb_ligne=*ligne;
nb_col=(int)((float)*n/(float)nb_ligne);
for (i=0;i<nb_col;i++)
res[i]=0.0;
for (i=0;i<nb_col;i++)
for (j=0;j<nb_ligne;j++)
{
res[i]+=x[compteur++];
}
}
Cette fonction est à compiler avec la ligne de commande R CMD SHLIB etc. (après avoir installé Rtools).
Il faut ensuite monter dynamiquement cette fonction dans R avec dyn.load(), et l'invoquer avec la fonction .C().
Voici l'invocation du benckmark :
Code : Tout sélectionner
library(microbenchmark)
set.seed(198)
dta <- matrix(rnorm(1e6), 1e3)
microbenchmark(colSums(dta),
.C("colSums_eric",x=as.double(dta),n=as.integer(1e6),ligne=as.integer(1e3),res=as.double(rep(0,1e6/1e3)))$res)
Et voici les résultats :
Code : Tout sélectionner
Unit: milliseconds
expr min lq mean median uq max neval cld
colSums(dta) 1.7554 1.7651 1.795682 1.78035 1.80745 2.6086 100 a
.C("colSums_eric", x = as.double(dta), n = as.integer(1e+06), ligne = as.integer(1000), res = as.double(rep(0, 1e+06/1000)))$res 5.6536 8.2946 14.257787 11.60260 14.64605 237.2044 100 b
De toute évidence, j'avais tord. La ré-écrite dans ce cas en C conduit à des calculs bien plus longs que les fonctions natives de R, surtout qu'elles sont je pense optimisées (compilées) dans les versions récentes de R. Le résultat serait encore plus catastrophique en prenant la comparaison avec du code parallélisé..
Bon, j'aurais essayé..
Mais il reste que l'interfaçage de R avec du C présente d'autres avantages vraiment importants, que j'utilise fréquemment.
AMitiés à tous, Eric.