¿Dónde puedo aprender cómo escribir código C a una velocidad de hasta R funciona lento? [cerrado]

StackOverflow https://stackoverflow.com/questions/4106174

  •  29-09-2019
  •  | 
  •  

Pregunta

¿Cuál es el mejor recurso para aprender cómo escribir código C para su uso con R? Sé sobre el sistema y las interfaces de idioma extranjero sección de extensiones R, pero me resulta muy difícil ir. ¿Cuáles son buenos recursos (tanto en línea como fuera de línea) para escribir código C para su uso con R?

Para aclarar, no quiero aprender cómo escribir código C, Quiero aprender cómo integrar mejor R y C. Por ejemplo, ¿cómo puedo convertir de un vector C entero en un vector de R número entero (o viceversa) o de un escalar C a un vector de R?

¿Fue útil?

Solución

Bueno, no es el bueno de Uso de la fuente, Lucas! --- R en sí tiene un montón de (muy eficiente) de código C se puede estudiar, y CRAN tiene cientos de paquetes, algunos de los autores tú confías. Eso proporciona ejemplos reales, prueba de estudio y adaptación.

Pero como sospechaba Josh, me inclino más hacia C ++ y por lo tanto RCPP . También tiene un montón de ejemplos.

Editar: Había dos libros que he encontrado útiles:

  • La primera de ellas es Venables y Ripley " S Programación " a pesar de que cada vez es más largo en el diente (y ha habido rumores de una segunda edición por años). En el momento no había nada más.
  • El segundo en Chambers ' Software de Análisis de Datos ', que es mucho más reciente y tiene un bonito tanto R centrado en la sensación - y dos capítulos sobre la extensión R. Tanto C y C ++ conseguir mencionado . Además, John me tritura por lo que hice con digest modo que por sí solo vale el precio de admisión.

Dicho esto, John está creciendo aficionado a RCPP (y contribuye) en que se encuentre el partido entre objetos R y objetos C ++ (a través de RCPP ) a ser muy natural - y ReferenceClasses ayuda allí.

Editar 2: con la pregunta reenfocado de Hadley, I muy fuertemente que instan a considerar C ++. Hay tanto sin sentido repetitivo que tiene que ver con C --- muy tedioso y muy evitables . Echar un vistazo a la RCPP-introducción viñeta . Otro ejemplo simple es esta entrada de blog donde muestro que en lugar de preocuparse por 10% diferencias (en uno de los ejemplos Radford Neal) que pueden obtener eightyfold aumenta con C ++ (en lo que es por supuesto un ejemplo artificial).

Editar 3: No hay complejidad en la que usted puede funcionar en C ++ errores que son, por decir lo menos, difícil de asimilar. Pero a poco utiliza RCPP en lugar de extender su posición, debe casi nunca lo necesita. Y si bien esto coste es innegable, es mucho eclipsado por el ventaja de código más simple, menos repetitivo, sin Protección / desprotección, sin la gestión de memoria, etc pp. Doug Bates ayer declaró que se encuentra en C ++ y RCPP a ser mucho más como escribir R que escribir en C ++. Tu caso es distinto y todo eso.

Otros consejos

Hadley,

definitivamente puede escribir código C ++ que es similar al código C.

Yo entiendo lo que dices de C ++ siendo más complicado de C. Esto es, si usted quiere dominar todo: objetos, plantillas, STL, la programación meta plantilla, etc ... la mayoría de la gente no necesita estas cosas y sólo puede depender de otros para ello. La implementación de RCPP es muy complicado, pero sólo porque no sabe cómo funciona su refrigerador, esto no significa que no se puede abrir la puerta y fresco grab leche ...

A partir de sus muchas contribuciones a la R, lo que me sorprende es que encuentres R (manipulación de datos, gráficos, manipulatio cuerda, etc ...) algo tedioso. Así prepararse para muchas más sorpresas con la API C interna de R. Esto es muy tedioso.

De vez en cuando, he leído los EXTOS-R o R-Ints manuales. Esto ayuda. Pero la mayoría de las veces, cuando realmente quiero averiguar acerca de algo, entro en la fuente R, y también en el origen de los paquetes escrito por ejemplo, Simon (por lo general hay mucho que aprender allí).

RCPP está diseñado para hacer que estos aspectos tediosos de la API desaparecen.

Puede juzgar por sí mismo lo que se encuentra más complicado, ofuscado, etc ... sobre la base de algunos ejemplos. Esta función crea un vector de caracteres mediante la API C:

SEXP foobar(){
  SEXP ab;
  PROTECT(ab = allocVector(STRSXP, 2));
  SET_STRING_ELT( ab, 0, mkChar("foo") );
  SET_STRING_ELT( ab, 1, mkChar("bar") );
  UNPROTECT(1);
}

El uso de RCPP, se puede escribir la misma función que:

SEXP foobar(){
   return Rcpp::CharacterVector::create( "foo", "bar" ) ;
}

o

SEXP foobar(){
   Rcpp::CharacterVector res(2) ;
   res[0] = "foo" ;
   res[1] = "bar" ;
   return res ;
}

Como Dirk dijo, hay otros ejemplos de las varias viñetas. También suele señalar a la gente hacia nuestras pruebas de unidad, porque cada uno de ellos ensayan una parte muy específica del código y algo son explica por sí mismo.

Obviamente estoy sesgado aquí, pero le recomiendo conseguir familiar en RCPP en lugar de aprender la API C de R y, a continuación, vienen a la lista de correo si algo no está claro o no parece factible con RCPP.

De todos modos, al final del argumento de venta.

Supongo que todo depende de qué tipo de código que desea escribir con el tiempo.

Romain

@hadley: por desgracia, no tengo recursos específicos en mente para ayudarle a empezar en C ++. La recogí de los libros de Scott Meyers (Efectiva C ++, C ++ más eficaz, etc ...), pero estos no son realmente lo que se podría llamar introductoria.

casi exclusivamente utilizar la interfaz .Llame a llamar a código C ++. La regla es bastante fácil:

  • La función C ++ debe devolver un objeto R. Todos los objetos R son SEXP.
  • La función C ++ tarda entre 0 y 65 R objetos como entrada (de nuevo SEXP)
  • debe (no realmente, pero podemos guardar para más tarde) se declaró con C vinculación, ya sea con extern "C" o RcppExport alias que define RCPP .

Así que una función .Llame se declaró como este en algún archivo de cabecera:

#include <Rcpp.h>

RcppExport SEXP foo( SEXP x1, SEXP x2 ) ;

e implementado como esto en un archivo .cpp:

SEXP foo( SEXP x1, SEXP x2 ){
   ...
}

No hay mucho más que saber acerca de la API R que se usa RCPP.

La mayoría de la gente sólo quiere tratar con vectores numéricos en RCPP. Esto se hace con la clase NumericVector. Hay varias maneras de crear un vector numérico:

A partir de un objeto existente que se pasa por debajo de R:

 SEXP foo( SEXP x_) {
    Rcpp::NumericVector x( x_ ) ;
    ...
 }

Con valores dados mediante el :: create función estática:

 Rcpp::NumericVector x = Rcpp::NumericVector::create( 1.0, 2.0, 3.0 ) ;
 Rcpp::NumericVector x = Rcpp::NumericVector::create( 
    _["a"] = 1.0, 
    _["b"] = 2.0, 
    _["c"] = 3
 ) ;

de un tamaño dado:

 Rcpp::NumericVector x( 10 ) ;      // filled with 0.0
 Rcpp::NumericVector x( 10, 2.0 ) ; // filled with 2.0

A continuación, una vez que tenga un vector, lo más útil es extraer un elemento de ella. Esto se hace con el operador [], con la indexación basada en 0, por lo que, por ejemplo, sumando los valores de un vector numérico es algo como esto:

SEXP sum( SEXP x_ ){
   Rcpp::NumericVector x(x_) ;
   double res = 0.0 ;
   for( int i=0; i<x.size(), i++){
      res += x[i] ;
   }
   return Rcpp::wrap( res ) ;
}

Pero con el azúcar RCPP podemos hacer esto mucho más agradable ahora:

using namespace Rcpp ;
SEXP sum( SEXP x_ ){
   NumericVector x(x_) ;
   double res = sum( x ) ;
   return wrap( res ) ;
}

Como he dicho antes, todo depende de qué tipo de código que desea escribir. Mira en lo que las personas hacen en paquetes que dependen de RCPP, compruebe las viñetas, las pruebas unitarias, vuelve a nosotros en la lista de correo. Estamos siempre dispuestos a ayudar.

@jbremnant: Eso es correcto. clases RCPP implementar algo parecido al patrón RAII. Cuando se crea un objeto RCPP, el constructor toma medidas apropiadas para asegurar la R objeto subyacente (SEXP) está protegido desde el colector de basura. El destructor se retira la protección. Esto se explica en el RCPP-intrduction viñeta . La implementación subyacente se basa en las funciones de la API R R_PreserveObject y R_ReleaseObject

En efecto, existe penalización en el rendimiento debido a la encapsulación C ++. Tratamos de mantener esto en un mínimo con inlining, etc ... La pena es pequeño, y si se toma en cuenta la ganancia en términos de tiempo que se tarda en escribir y mantener código, no es tan relevante.

Llamar a funciones de investigación de la función de clase RCPP es más lento que llamar directamente eval con la API C. Esto se debe a que tomamos precauciones y envolver la llamada de función en un bloque TryCatch para que podamos capturar errores R e impulsarlas a excepciones de C ++ para que puedan ser tratados mediante el try / catch estándar en C ++.

La mayoría de la gente quiere vectores de uso (especialmente NumericVector), y la pena es muy pequeño, con esta clase. El directorio de ejemplos / ConvolveBenchmarks contiene varias variantes de la función de convolución notorio desde r-exts y la viñeta tiene resultados de referencia. Resulta que RCPP hace que sea más rápido que el código de referencia que utiliza la API R.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top