Cette séance présente un condensé des notions abordées durant l’ANF R pour le calcul
qui a eu lieu du 5 au 9 octobre au centre CNRS d’Aussois. De plus amples informations sur cette ANF, ainsi que les supports de formation sont disponible sur le site du groupe Calcul, à l’adresse suivante : ANF R pour le calcul
L’idéal est disposer d’une machine avec un système d’exploitation type unix (Linux ou Mac) car certaines fonctionnalités (parallélisation de type “forking”) ne fonctionnent pas sous Windows.
Les packages suivants sont nécessaires au bon déroulement de la séance :
devtools
: offre de nombreux outils d’assistance au développement de ressources pour R ;roxygen2
: outil d’aide à la préparation de la documentation de packages. Devrait être installé lors de l’installation de devtools
;Rcpp
: permet l’intégration simple de codes C++ dans des scripts R ;foreach
: un package développé par Revolution Analytics permettant la parallélisation de calculs sous tous les systèmes d’exploitation ;parallel
: gère la parallélisation de certaines procédures (typiquement les fonctions apply
) ;microbenchmark
: permet de comparer les performances (en terme de temps de calcul) de plusieurs procédures ;ggplot2
: fournit un grand nombre de fonctions graphiques basées sur la “grammaire des graphiques” ;jpeg
: permet d’importer des fichiers de type JPEG
sous la forme d’un tableau contenant les valeurs des canaux Red, Green, Blue (RGB) de l’image ;FactoMineR
: un package dévolu à l’analyse de données.Exécuter le bloc d’instructions suivantes :
install.packages(c('devtools', 'Rcpp', 'foreach', 'microbenchmark', 'ggplot2', 'jpeg', 'FactoMineR'))
library('devtools')
library('Rcpp')
library('foreach')
library('microbenchmark')
library('parallel')
library('ggplot2')
library('jpeg')
library('FactoMineR')
Le déroulement de la séance sera grandement facilitée par l’utilisation de RStudio
, interface de développement pour R. Au besoin, le télécharger à l’adresse suivante : RStudio.
RStudio permet de profiter des possibilités des systèmes de gestion de versions git
et subversion
s’ils sont installés.
De tels logiciels permettent d’associer à un projet de développement, un historique des modifications apportées aux scripts, de gérer le développement d’un même script selon des branches parallèles et de partager les ressources avec des collaborateurs. L’utilisation d’un tel système est fortement recommandé lorsque l’on souhaite développer un package R. Se reporter aux sites web des deux logiciels :
Depuis le bureau virtuel, entrer dans le cours Utilisateurs de R
puis télécharger l’ensemble des fichiers contenus dans le répertoire Didacticiel > Création de packages
.
Parmi ces fichiers, figurent :
un exemple de package “maison”, que l’on va décortiquer pendant la séance : acpjpeg_0.0.1.tar.gz
;
le contenu des fichiers sources de ce package sous forme d’une archive zip : acpjpeg_0.0.1.zip
;
les supports des formations de l’ANF R pour le calcul
dont ce didacticiel s’inspire.
acpjpeg
Le package “maison” acpjpeg
fournit une fonction nommée pcajpeg
qui prend en argument le chemin vers un fichier d’extension .jpeg
et crée deux nouvelles images de même taille correspondant à la projection des canaux RGB respectivement sur l’axe principal et le plan principal obtenu lors de l’ACP de ces canaux.
Ce package n’étant pas hébergé par le CRAN, il faut l’installer depuis le répertoire dans lequel il est placé. Pour cela, exécuter la commande suivante
Puis pour le charger :
library('acpjpeg')
Pour tester le fonctionnement du package, on pourra copier le bloc d’instructions fourni en exemple dans le fichier d’aide associé à la fonction pcajpeg
, reproduit ici :
data(lenna)
jpeg::writeJPEG(lenna, target='lenna.jpeg')
pcajpeg(file="lenna.jpeg")
## M S
## [1,] 0.5558455 0.2346776
## [2,] 0.3311799 0.1729088
## [3,] 0.2754439 0.1426447
## [1] "Done!"
Ces instructions ont pour effet de créer trois fichiers d’extension .jpeg
dans le répertoire de travail :
lenna.jpeg
est l’image à laquelle on va appliquer la transformation ;img1.jpeg
et img2.jpeg
sont les images produites par la fonction pcajpeg
.Image originale de Lenna
Image reconstituée à partir de la composante principale
Image reconstituée à partir des deux composantes principales
L’exécution de cette fonction est lente. On a pour but de diagnostiquer les raisons de ce manque de performances et d’y remédier.
Les fichiers sources du package sont accessibles depuis l’une ou l’autre des archives acpjpeg_0.0.1.tar.gz
ou acpjpeg_0.0.1.zip
: il suffit de les décompresser.
Cette archive contient :
R
contient l’ensemble des scripts R nécessaires au bon fonctionnement du package. Ici, il y a un unique script nommé ACPJPEG.R
;data
contient les jeux de données associés au package. Ici, un seul fichier lenna.RData
;man
contient les fichiers de documentation (d’extension .Rd
) associés aux fonctions et aux jeux de données du package. Il faut un fichier de documentation pour chaque fonction disponible et chaque jeu de données, ainsi qu’un fichier de document général pour le package. C’est à partir de ces fichiers de documentation que les fichiers d’aide (sous forme html ou pdf) sont générés. Ici, il y en a trois : acpjpeg-package.Rd
, pcajpeg.Rd
et lenna.Rd
;src
contient les fichiers sources externes, tels que sccripts C++ ou FORTRAN, etc. Ici, deux scripts C++ : CalcMS.cpp
et RcppExports.cpp
;build
contient des fichiers de configuration générés pendant la construction du package ;DESCRIPTION
est le fichier d’ “identité” du package ;NAMESPACE
configure le chargement de fonctions provenant de packages externes et l’exportation de certaines fonctions définis dans les scripts R, dans l’environnement global lorsque le package est chargé.On détaillera plus tard le contenu et les règles d’édition de ces différents dossiers et fichiers.
Un outil simple de diagnostic de la performance d’une procédure est l’outil de profilage de R : on va lancer la procédure à analyser en demandant à R de relever périodiquement la tâche en cours d ’exécution. On génère ainsi un fichier d’extension .out
dans lequel on trouve le nom de la tâche en cours d’exécution à chaque pas de temps.
Voici en action cet outil de profilage :
Rprof(filename = 'TestACPJPEG.out', interval=0.005)
pcajpeg('lenna.jpeg')
Rprof()
summaryRprof('TestACPJPEG.out')$by.total
## total.time total.pct self.time self.pct
## "<Anonymous>" 30.480 100.00 0.000 0.00
## "block_exec" 30.480 100.00 0.000 0.00
## "call_block" 30.480 100.00 0.000 0.00
## "process_file" 30.480 100.00 0.000 0.00
## "process_group" 30.480 100.00 0.000 0.00
## "process_group.block" 30.480 100.00 0.000 0.00
## "withCallingHandlers" 30.480 100.00 0.000 0.00
## "in_dir" 30.465 99.95 0.000 0.00
## "pcajpeg" 16.540 54.27 0.015 0.05
## "eval" 16.540 54.27 0.000 0.00
## "evaluate_call" 16.540 54.27 0.000 0.00
## "handle" 16.540 54.27 0.000 0.00
## "withVisible" 16.540 54.27 0.000 0.00
## "PCA" 14.650 48.06 0.025 0.08
## "plot.PCA" 14.295 46.90 0.025 0.08
## "FUN" 13.930 45.70 0.005 0.02
## "lapply" 13.930 45.70 0.000 0.00
## ".External2" 13.920 45.67 13.920 45.67
## "in_base_dir" 13.920 45.67 0.000 0.00
## "mapply" 13.920 45.67 0.000 0.00
## "plot2dev" 13.920 45.67 0.000 0.00
## "unlist" 13.920 45.67 0.000 0.00
## "wrap" 13.920 45.67 0.000 0.00
## "wrap.list" 13.920 45.67 0.000 0.00
## "wrap.recordedplot" 13.920 45.67 0.000 0.00
## "print" 13.895 45.59 0.000 0.00
## "print.recordedplot" 13.895 45.59 0.000 0.00
## "replayPlot" 13.895 45.59 0.000 0.00
## "text" 9.850 32.32 0.010 0.03
## "text.default" 9.840 32.28 9.815 32.20
## "points" 4.355 14.29 0.010 0.03
## "plot.xy" 4.350 14.27 4.350 14.27
## "points.default" 4.345 14.26 0.000 0.00
## "CalcMS1" 1.670 5.48 1.580 5.18
## "array" 0.090 0.30 0.090 0.30
## "colnames<-" 0.090 0.30 0.090 0.30
## "dimnames" 0.065 0.21 0.000 0.00
## "dimnames.data.frame" 0.065 0.21 0.000 0.00
## "row.names" 0.065 0.21 0.000 0.00
## "rownames" 0.065 0.21 0.000 0.00
## "row.names.data.frame" 0.065 0.21 0.000 0.00
## "svd.triplet" 0.065 0.21 0.000 0.00
## "as.character" 0.060 0.20 0.060 0.20
## "t" 0.060 0.20 0.000 0.00
## "t.default" 0.045 0.15 0.045 0.15
## ".External" 0.040 0.13 0.040 0.13
## "dev.off" 0.040 0.13 0.000 0.00
## "*" 0.035 0.11 0.035 0.11
## ".Call" 0.035 0.11 0.035 0.11
## "cbind" 0.035 0.11 0.035 0.11
## "doTryCatch" 0.035 0.11 0.000 0.00
## "tryCatch" 0.035 0.11 0.000 0.00
## "tryCatchList" 0.035 0.11 0.000 0.00
## "tryCatchOne" 0.035 0.11 0.000 0.00
## "writeJPEG" 0.035 0.11 0.000 0.00
## "(" 0.030 0.10 0.030 0.10
## "matrix" 0.030 0.10 0.030 0.10
## "svd" 0.030 0.10 0.005 0.02
## "tryCatch.W.E" 0.030 0.10 0.000 0.00
## "/" 0.025 0.08 0.025 0.08
## "La.svd" 0.025 0.08 0.015 0.05
## "as.vector" 0.025 0.08 0.010 0.03
## "plot" 0.025 0.08 0.000 0.00
## "plot.default" 0.025 0.08 0.000 0.00
## "plot.new" 0.025 0.08 0.000 0.00
## "+" 0.020 0.07 0.020 0.07
## "as.double" 0.020 0.07 0.020 0.07
## "sqrt" 0.020 0.07 0.020 0.07
## "xy.coords" 0.020 0.07 0.000 0.00
## "%*%" 0.015 0.05 0.015 0.05
## "c" 0.015 0.05 0.015 0.05
## "crossprod" 0.015 0.05 0.005 0.02
## "as.matrix" 0.015 0.05 0.000 0.00
## "^" 0.010 0.03 0.010 0.03
## "-" 0.010 0.03 0.010 0.03
## "!=" 0.010 0.03 0.010 0.03
## "min" 0.010 0.03 0.010 0.03
## "rownames<-" 0.010 0.03 0.010 0.03
## "do.call" 0.010 0.03 0.000 0.00
## "is.na" 0.010 0.03 0.000 0.00
## "is.na.data.frame" 0.010 0.03 0.000 0.00
## "any" 0.005 0.02 0.005 0.02
## "attr" 0.005 0.02 0.005 0.02
## "cor" 0.005 0.02 0.005 0.02
## "data.frame" 0.005 0.02 0.005 0.02
## "is.finite" 0.005 0.02 0.005 0.02
## "rbind" 0.005 0.02 0.005 0.02
## "rowSums" 0.005 0.02 0.005 0.02
## "as.data.frame" 0.005 0.02 0.000 0.00
## "as.data.frame.matrix" 0.005 0.02 0.000 0.00
## "ec.tab" 0.005 0.02 0.000 0.00
## "eigen" 0.005 0.02 0.000 0.00
## "fun" 0.005 0.02 0.000 0.00
## "handle_output" 0.005 0.02 0.000 0.00
## "lines" 0.005 0.02 0.000 0.00
## "lines.default" 0.005 0.02 0.000 0.00
## "moy.ptab" 0.005 0.02 0.000 0.00
## "parse_all" 0.005 0.02 0.000 0.00
## "parse_all.character" 0.005 0.02 0.000 0.00
## "plot_snapshot" 0.005 0.02 0.000 0.00
## "recordPlot" 0.005 0.02 0.000 0.00
## "try" 0.005 0.02 0.000 0.00
## "unname" 0.005 0.02 0.000 0.00
Le résultat obtenu est un data-frame (tableau) dont les lignes correspondent aux différentes tâches exécutées (typiquement, des noms de fonctions) par R lors l’appel de pcajpeg('lenna.jpeg')
. Ce data-frame contient quatre colonnes :
total.time
correspond au temps cumulé passé à exécuter la commande (plus précisément au nombre de fois où cette tâche a été relevée, multiplié par la période) ;total.pct
est le pourcentage de temps cumulé passé à exécuter la commande ;seft.time
est le temps propre passé à exécuter la commande : on peut passer beaucoup de temps à l’intérieur d’une fonction, car elle fait appel à d’autres fonctions. Le temps propre est donc le temps passé à exéctuer des tâches propres à cette fonction, en excluant l’appel aux autres fonctions ;seft.time
est le pourcentage de temps propre passé à exécuter la commande (par rapport au temps total d’exécution).Les tâches sont rangées par ordre décroissant de temps d’exécution. Ici, on passe 100% du temps de l’exécution dans la fonction pcajpeg
(c’est bien normal, psuique c’est la seule qu’on exécute), dont environ 90% du temps dans plot.PCA
.
Cette dernière fonction provient du package FactoMineR
et sert à représenter le nuage de points projeté surle plan principal lors de l’ACP. C’est ici parfaitement inutile ; on va donc modifier le code source pour ne pas effectuer cette étape.
Pour cela, on va recréer un package à partir des fichiers sources inclus dans les archives acpjpeg_0.0.1.tar.gz
ou acpjpeg_0.0.1.zip
…
La création et la distribution d’un package R sont codifiées par le CRAN et doivent être menées avec rigueur. R propose de nombreux outils pour faciliter la création de packages, conformes aux exigences du CRAN, dont on illustrera certains dans la suite. On pourra se reporter au document de référence Writing R extensions
pour plus de détails, disponible à l’adresse suivante : Writing R Extensions manual.
RStudio offre un certain nombre d’outils visant à faciliter la création et le développement de packages pour R. Dans cette partie, on se propose d’illustrer ces mécanismes pour créer un nouveau package acpjpeg
optimisant celui déjà fourni.
Pour cela, on pourra suivre les instructions suivantes :
File
> New Project...
New directory
> R package
. Dans la boîte de dialogue qui s’ouvre,
Type:
, choisir Package w/Rcpp
(le package contiendra des scripts C++ incorporés au moyen du package Rcpp
) ;package name:
;Browse...
;Create a git repository
pour associer à ce projet un dépôt git que l’on pourra ensuite synchroniser avec un dépôt distant ;use packrat with this project
;ACPJPEG.R
dans la fenêtre Create package based on source files
;Create Project
.Boîte de dialogue de RStudio lors de la création assistée d’un package.
Dans le répertoire spécifié, apparaît alors un nouveau répertoire nommé acpjpeg
contenant les répertoires R
, man
et src
décrits précédemment, ainsi que les fichiers DESCRIPTION
et NAMESPACE
. Un dernier fichier est présent : exemplepkg.Rproj
, qui est un fichier de configuration propre à RStudio, configurant la sauvegarde automatique de l’historique des commandes et de l’environnement global de la session de R attachée au projet (ce fichier n’est donc pas directement lié à la création du package).
Le répertoire R
contient le script ACPJPEG.R
. Les autres répertoires sont vides. Effectuer les actions suivantes :
CalcMS.cpp
dans le répertoire src
;data
puis y copier/coller le fichier lenna.RData
.Le fichier DESCRIPTION
contient les données identitaires du package. Certains attributs ont été automatiquement renseignés :
Package: acpjpeg
: c’est le nom du package ;Type: Package
;Version : 1.0
: remplacer la version par 0.0.2
;Date: 2015-10-13
;License: GPL (>= 2)
.D’autres doivent être obligatoirement renseignés :
Title:
Un bref titre décrivant les fonctionnalités du package.Author:
: la liste des auteurs et leur rôle (voir le manuel Writing R extensions
pour plus de détails). Ici, on pourra saisir Prenom Nom [aut, cre]
.Maintainer:
: la personne en charge de la maintenance du package. Le mail de cette personne doit être saisie entre <>
. Ici, taper Prenom Nom <prenom.nom@truc.fr>
;Description:
Un paragraphe décrivant les fonctionnalités du package. Doit respecter les règles de syntaxe : commencer par une Majuscule, finir par un point, etc.Enfin, pour que le package soit fonctionnel, il faut déclarer les dépendances à d’autres packages. Rajouter pour cela :
Depends: R (>= 3.2.2)
: la liste des packages sans lesquels l’existence du package est injustifié. Par exemple, si l’on développe un package de fonctions graphiques associées aux objets définis dans un autre package. On décrale généralement la version de R minimale nécessaire (ou à défaut, celle sur laquelle a été développée le package) ;Imports: Rcpp (>= 0.12.1), jpeg (>= 0.1-8), FactoMineR (>= 1.31.3), foreach (>= 1.4.2)
: la liste des packages (avec leur version minimale) nécessaires au fonctionnement des scripts ;LinkingTo : Rcpp
: liste des packages dont on utilise les “header files”.Roxygen2
.Créer un fichier de documentation associée au jeu de données lenna.RData
. Pour cela,
File
> New file
> R_Documentation
;Topic name
, inscrire lenna
;Dataset
dans le menu déroulant Rd template
.Un fichier-type est créé ; il suffit de le compléter, par exemple, en copiant et collant le contenu du fichier lenna.Rd
contenu dans l’archive acpjpeg_0.0.1.tar.gz
(on peut tout aussi bien copier/coller le fichier directement…).
La création de la documentation pour les focntions à exporter peut être facilitée par l’utilisation de Roxygen2
. Pour cela,
Tools
> Project Options...
;build tools
puis cocher la case Generate documentation with Roxygen
;Rd files
, NAMESPACE file
, R CMD check
et Source and binary package builds
.On peut alors pré-renseigner la documentation à l’intérieur du script, en ajoutant juste avant la déclaration de la fonction un paragraphe d’instructions à destination de Roxygen (chaque ligne commencera par #'
, ce qui permet à Roxygen de reconnaitre les instructions qui le concernent). Voici le paragraphe à ajouter en préambule de la décalration de la fonction pcajpeg
:
#' PCA on the RGB channels of a JPEG file
#'
#' JPEG images are converted into a n*3 matrix, where n stands for the number of pixels in the image and
#' the columns are the Red, Green and Blue (RGB) channels of the pixels. Then, a PCA is performed.
#' Outputs are two JPEG images obtained by projecting the original one to the (two) principal component(s).
#' @param file Character string specifying the path to the JPEG file to analyse
#' @return Produces two JPEG files named img1.jpeg and img2.jpeg.
#' img1.jpeg is obtained from file by conserving only the first principal component.
#' img2.jpeg is obtained from file by conserving only the two first principal component(s).
#' @examples
#' data(lenna)
#' jpeg::writeJPEG(lenna, target='lenna.jpeg')
#' pcajpeg(file="lenna.jpeg")
#' @export
La première ligne est le tire. Un espace blanc sépare le tire du paragraphe de description du package, qui peut s’étaler sur plusieurs lignes. Suivent la description des variables (une ligne par variable, préfixée par @param
) puis des sorties (de même, si la sortie est une liste de plusieurs composantes, une ligne par composante, préfixée par @return
), etc. On finit par la commande @export
De meme, on peut inclure un code spécifique à la fin d’un script pour générer le fichier NAMESPACE
. Voici le bloc d’instructions à ajouter à la fin du script ACPJJPEG.R
pour renseigner le fichier NAMESPACE :
#' @useDynLib acpjpeg
#' @import foreach
#' @importFrom Rcpp sourceCpp
NULL
#' @importFrom jpeg readJPEG
NULL
#' @importFrom jpeg writeJPEG
NULL
#' @importFrom FactoMineR PCA
NULL
#' @importFrom parallel mclapply
NULL
Pour créer les fichiers de documentation, il suffit alors de cliquer dans la barre de menu de RStudio
sur Build
> Document
.
Ouvrir le fichier ACPJPEG.R
dans RStudio. Pour supprimer le rendu graphique lors de l’ACP, ajouter l’option graph=FALSE
dans l’appel de la fonction PCA
.
Pour construire le package, dans la barre de menu de RStudio, cliquer sur Build
> Build source package
. Une archive acpjpeg_0.0.1.tar.gz
est alors créée.
Avant de l’installer, il est nécessaire de vérifier qu’elle satisfait aux exigences du CRAN (même si l’on ne compte pas soumettre ce package à la communauté). Pour cela, cliquer sur Build
> Check package
.
Il y a trois types d’avertissements, rangés par ordre décroissant d’importance :
ERROR
: une erreur dans votre script R ou lors d’appels à des fonctions d’autres pacakges, lors de l’évaluation des exemples des fichiers de documentation, etc. Généralement, la rencontre d’un erreur interrompt la vérification du package : il est indispensable de corriger cette erreur ;
WARNING
: signale des manquements importants aux règles d’édition d’un package : fichiers de documentation absents ou mal remplis, options de construction (R CMD build
) mal ajustées, etc. Ces avertissements doivent être corrigées avant d’envisager une soumission du package au CRAN ;
NOTE
: des irrégularités secondaires qui ne nuisent pas à proprement parler au fonctionnement et à l’accessibilité du package. Ces irrégularités doivent être levées autant que possible. En cas de soumission au CRAN, toute note non levée devra être justifiée.
Une vérification plus stricte peut être effectuée en ajoutant l’option as-cran
à la commande de vérification. Pour cela, cliquer sur Tools
> Project options...
, cliquer sur l’icône build tools
. Dans le champ Check package
, ajouter --as-cran
.
En l’état actuel, le package acpjpeg
ne devrait pas produire de message d’erreur ; éventuellement des avertissements et des notes que l’on pourra corriger en se reportant aux indications fournies dans la partie supérieure droite de RStudio (onglet build
).
Si un dépôt git a été associé au projet, une icône git apparaît dans la barre d’outils sous la barre de menu de RStudio. Cliquer dessus, puis sur Commit
. Une boîte de dialogue vous invite à choisir les fichiers à déposer parmi ceux qui ont été modifié. Une fois les fichiers choisis, cliquer sur le bouton Commit
pour soumettre (et valider) les modifications. Ne pas oublier
Désinstaller l’ancienne version du package :
remove.packages('acpjpeg')
Puis installer et charger la version fraichement créée :
install.packages('acpjpeg_0.0.2.tar.gz', repos=NULL)
library('acpjpeg')
Relancer le profilage du code :
data(lenna)
jpeg::writeJPEG(lenna, target='lenna.jpeg')
Rprof(filename = 'TestACPJPEG2.out', interval=0.005)
pcajpeg('lenna.jpeg')
Rprof()
summaryRprof('TestACPJPEG2.out')$by.total
L’exécution est bien plus rapide ; le profilage met cependant en évidence le temps d’exécution important de la fonction CalcMS1
. En explorant le script acpjpeg
, on comprend que cette fonction sert à calculer la moyenne et l’écart-type des trois canaux de couleurs, mais qu’elle est très mal implémentée… En particulier, les boucles for
sont à proscrire, les fonctions doivent être “vectorisées” au maximum, il faut éviter de reproduire les mêmes évaluations plusieurs fois, etc.
Le script ACPJPEG
contient cinq autres fonctions permettant le calcul de la moyenne et de l’écart-type des canaux de couleurs, dont voici un bref descriptif :
CalcMS2
: utilise la fonction apply
appliquée à l’image représentée sous forme d’une matrtice à trois colonnes, pour calculer moyenne et écart-type ;CalcMS3
: utilise la fonction mclapply
du package parallel
pour “paralléliser”" le calcul des moyenne et écart-type : les moyennes et écart-types des 3 canaux seront calculés en parallèles sur 3 threads(si la machine utilisée dispose d’au moins 3 threads. Sous linux, il peut être utile d’installer le package hwloc
et d’exécuter la commande hwloc-ls
dans un terminal pour obtenir une description de la composition de la machine utilisée) ;CalcMS4
: utilise un appel à un script C++ pour calculer moyennes et écart-types ;CalcMS5
: idem, en parallélisant les calculs à l’aide de la fonction mclapply
;calcMS6
: idem, à la différence que la parallélisation est gérée directement dans C++ grâce à openMP.Pour comparer les temps d’exécution de ces fonctions, exécuter le bloc d’instructions suivant :
library('microbenchmark')
source('acpjpeg/R/ACPJPEG.R') #Modifier le chemin si nécessaire
Rcpp::sourceCpp('acpjpeg/src/CalcMS.cpp') #Idem
img <- readJPEG('lenna.jpeg')
d <- dim(img)
n <- d[1] #largeur
m <- d[2] #Hauteur
R <- as.numeric(img[,,1])
G <- as.numeric(img[,,2])
B <- as.numeric(img[,,3])
imgAsMat <- cbind(R,G,B)
imgAsLst <- list(R,G,B)
bm <- microbenchmark(
degueux = CalcMS1(imgAsMat),
apply = CalcMS2(imgAsMat),
mclapply = CalcMS3(imgAsLst),
cpp = CalcMS4(imgAsMat),
parcpp = CalcMS5(imgAsLst),
cpppar = CalcMS6(imgAsLst),
times=10L
)
bm
## Unit: milliseconds
## expr min lq mean median uq
## degueux 1267.182434 1278.029249 1300.603768 1293.15782 1315.379100
## apply 24.668747 30.813034 31.779283 31.86485 33.514289
## mclapply 18.756819 23.923537 31.314417 28.55452 40.788278
## cpp 21.368379 23.374662 36.879924 27.47769 32.051455
## parcpp 17.151067 19.211310 23.077798 21.20411 24.682298
## cpppar 1.352756 1.371408 2.247578 1.91857 3.567902
## max neval
## 1381.061745 10
## 36.114844 10
## 41.720928 10
## 113.796682 10
## 38.555662 10
## 3.866598 10
Dans le script ACPJPEG.R
, après la déclaration des vairables R
, G
et B
, ajouter la ligne imgAsLst <- list(R,G,B)
et remplacer la commande CalcMS1(imgAsMAt)
par CalcMS6(imgAsLst)
. Reconstruire et vérifier le package;
Les fonctions CalcMS3
, CalcMS5
et CalcMS6
font appel à du code C++ inclus dans R au moyen du package Rcpp
(précisément aux fonctions moy
, moy2
, ect
et ect2
incluses dans le script CalcMS.cpp
dans le répertoir src
).
Ouvrir le script CalcMS.cpp
dans RStudio. Ce fichier contient des d’instructions d’en-tête permettant d’appeler des fonctions et des classes définis dans d’autres fichiers (définis dans le package Rcpp
) :
#include<Rcpp.h> //Pour utiliser les classes et fonctions définis dans Rcpp
#include<omp.h> //Idem, pour parallelisation via openMP
using namespace Rcpp;
Le reste du script contient du code C++ classique ; pour exporter les fonctions définis vers R, il suffit de faire précéder la déclaration de la fonction par l’instruction
// [[Rcpp::export]]
puis de “sourcer” le script via la commande
Rcpp::sourceCpp('acpjpeg/src/CalcMS.cpp')
On peut alors faire appel aux fonctions définies dans le script C++, directement dans R :
moy2(1:10)
## [1] 5.5