Manipulation de masortingces de C à R

Je veux écrire quelques fonctions de manipulation de la masortingce en C, puis les transmettre à R, où la masortingce sera fournie par R, et obtenir les résultats des manipulations. J’ai une fonction de test comme indiqué ci-dessous (ne vous souciez pas de ce que cela fait, dans mes fonctions d’origine, je devrai choisir un élément aléatoire de chaque ligne, faire quelques calculs et renvoyer un tableau composé aléatoirement de ces éléments. éléments choisis de chaque ligne, en d’autres termes, il me faut deux boucles pour parcourir tous les éléments de la masortingce).

void multMat(double **A, int *r, int *c, double *s) { int i, j; for (i = 0; i < *r; ++i) { for (j = 0; j < *c; ++j) { if (j == 5) s[i] = A[i][j] * A[i][0]; } } } 

J’ai compilé cela avec R CMD SHLIB multMat.c , et il produit multMat.so pour moi. Ensuite, côté R, j’ai quelque chose comme ceci:

 dyn.load("multMat.so") multMat <- function(A) { .C("multMat", A=as.double(A), r=as.integer(nrow(A)), c=as.integer(ncol(A)), s=as.double(nrow(A))) } 

Ensuite, j’ai créé une masortingce de test similaire à celle de R Studio et j’ai appelé cette fonction:

 A <- matrix(1:100, 10, 10) multMat(A) 

Le problème est que lorsque je lance cette fonction, R Studio se bloque. Je suppose qu’il y a un problème avec la définition de la fonction C. Des idées?

Où tu te trompes

Vous définissez A comme double ** ,

 void multMat(double **A, int *r, int *c, double *s) 

en passant un double * :

 .C("multMat", A=as.double(A), r=as.integer(nrow(A)), c=as.integer(ncol(A)), s=as.double(nrow(A))) 

Vous devriez réécrire votre fonction C en utilisant un tableau à 1 dimension. Définissez votre fonction comme:

 void multMat(double *A, int *r, int *c, double *s) 

et remplacez A[i][j] par A[j * r + i] . (Si je ne vous ai pas mal compris, r est la dimension principale.)

Problème de performance:

Pour le moment, il s’agit de la boucle ij avec la boucle j-loop comme j-loop interne, de sorte que vous balayez une ligne de la masortingce dans la boucle la plus à l’intérieur. Ce n’est pas convivial en cache . Vous devriez échanger la boucle pour obtenir la boucle ji .

Je pense que vous êtes en fait au courant du problème de cache. En C, les masortingces sont stockées dans un ordre de rangée majeur, de sorte que la boucle ij est optimale; mais dans R, les masortingces sont stockées dans l’ordre des colonnes, ji loop est donc optimal.

Peut-être que le style de stockage différent des masortingces posera un problème pour votre code existant. Vous pouvez le penser deux fois ici. Votre code C d’origine suppose qu’il faut une masortingce stockée par ligne, tandis que si vous initialisez votre masortingce dans R et l’alimentez en C, elle est stockée par colonne. Peut-être que quelques changements sont nécessaires. Si cela entraîne trop de changements dans votre code, vous pouvez essayer de passer la transposition de votre masortingce R à C.

Vous devez également utiliser davantage de variables locales / automatiques dans votre code C, au lieu d’utiliser des pointeurs . Par exemple, remplacez

 for (i = 0; i < *r; ++i) 

par

 int r_local = *r; for (i = 0; i < r_local; ++i) 

Vous obtenez des améliorations de performances grâce à la réutilisation du registre de la CPU et à la réduction des instructions (inutile de déréférencer le point à chaque itération).

R pris en charge le type de données C / FORTRAN

Donc, il n'y a aucun moyen de passer directement la masortingce de R, puis d'utiliser la convention occasionnelle pour masortingce, ce qui signifie A[i][j] dans le côté C?

Non, il n'y en a pas. R ne prend pas en charge le double ** . Les masortingces dans R sont stockées dans column-major-format dans un vecteur long et appartiennent au type double * .

 R storage mode C type FORTRAN type logical int * INTEGER integer int * INTEGER double double * DOUBLE PRECISION complex Rcomplex * DOUBLE COMPLEX character char ** CHARACTER*255 raw unsigned char * none 

Voir la section 5.2 de l’écriture des extensions R.