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

Avant de démarrer…

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 :

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')

Les logiciels à installer

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 :

Les fichiers à télécharger

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.

Le package maison 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.

Installation et chargement du package

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')

Utilisation

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 originale de Lenna

Image reconstituée à partir de la composante principale

Image reconstituée à partir de la composante principale

Image reconstituée à partir des deux composantes principales

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 entrailles du package

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 :

  • cinq dossiers dont les contenus sont les suivants :
    • 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 ;
  • deux fichiers de configuration 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.

Profilage de code

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 :

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

Création et développement d’un package

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.

Création assistée avec RStudio

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 :

  • dans la barre de menu, cliquer sur File > New Project...
  • Choisir New directory > R package. Dans la boîte de dialogue qui s’ouvre,
    • dans le menu déroulant Type:, choisir Package w/Rcpp (le package contiendra des scripts C++ incorporés au moyen du package Rcpp) ;
    • renseigner le nom du package dans le champs package name:;
    • sélectionner le répertoire approprié en cliquant sur le bouton Browse... ;
    • si le SGV git est installé, cocher 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 ;
    • décocher use packrat with this project ;
    • ajouter le fichier ACPJPEG.R dans la fenêtre Create package based on source files ;
    • cliquer sur le bouton Create Project.
Boîte de dialogue de RStudio lors de la création assistée d’un package.

Boîte de dialogue de RStudio lors de la création assistée d’un package.

Contenu du 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 :

  • copier/coller le script CalcMS.cpp dans le répertoire src ;
  • créer un répertoire data puis y copier/coller le fichier lenna.RData.

Edition du fichier DESCRIPTION

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”.

Génération assistée des fichiers de documentation avec Roxygen2.

Créer un fichier de documentation associée au jeu de données lenna.RData. Pour cela,

  • dans la barre de menu, cliquer sur File > New file > R_Documentation ;
  • dans le champs Topic name, inscrire lenna ;
  • choisir 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,

  • dans la barre de menu de RStudio, cliquer sur Tools > Project Options... ;
  • cliquer sur l’icône build tools puis cocher la case Generate documentation with Roxygen ;
  • dans la boîte de dialogue qui s’ouvre, coher 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.

Modification du script

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.

Reconstruction et vérification du package

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).

Ajouter les fichiers modifiées au dépôt git

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

Optimisation du code : parallelisation et inclusion de code C++

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 :

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;

Inclusion de scripts C++ grâce à Rcpp

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