nieve, en línea y Rcpp:

Rcpp una función en Rcpp y la compilé con en inline . Ahora, quiero ejecutarlo en paralelo en diferentes núcleos, pero obtengo un error extraño. Aquí hay un ejemplo mínimo, donde la función funCPP1 se puede comstackr y funciona bien por sí misma, pero no puede clusterCall función clusterCall . La función funciona bien como un proceso único, pero da el siguiente error cuando se ejecuta en paralelo:

 Error in checkForRemoteErrors(lapply(cl, recvResult)) : 2 nodes produced errors; first error: NULL value passed as symbol address 

Y aquí hay un código:

 ## Load and compile library(inline) library(Rcpp) library(snow) src1 <- ' Rcpp::NumericMatrix xbem(xbe); int nrows = xbem.nrow(); Rcpp::NumericVector gv(g); for (int i = 1; i < nrows; i++) { xbem(i,_) = xbem(i-1,_) * gv[0] + xbem(i,_); } return xbem; ' funCPP1 <- cxxfunction(signature(xbe = "numeric", g="numeric"),body = src1, plugin="Rcpp") ## Single process A <- matrix(rnorm(400), 20,20) funCPP1(A, 0.5) ## Parallel cl <- makeCluster(2, type = "SOCK") clusterExport(cl, 'funCPP1') clusterCall(cl, funCPP1, A, 0.5) 

Piénselo bien, ¿qué hace en línea? Crea una función C / C ++ para usted, luego la comstack y la vincula a una biblioteca compartida cargada dinámicamente. ¿Dónde se sienta ese? En el directorio temporal de R

Así que probé lo correcto al enviar la interfaz R que llamaba a esa biblioteca compartida al otro proceso (¡que tiene otro directorio temporal!), Pero eso no incluye el archivo dll / so allí.

Por lo tanto, el consejo es crear un paquete local, instalarlo y tener ambos procesos de nieve cargados y llamarlo.

(Y como siempre: se pueden tener respuestas de mejor calidad en la lista rcpp-devel, que son leídas por más constructores de Rcpp que SO es).

Una vieja pregunta, pero me encontré con ella mientras miraba las tags Rcpp principales, así que tal vez esta respuesta sea útil.

Creo que la respuesta de Dirk es correcta cuando el código que ha escrito está completamente desactivado y hace lo que quiere, pero puede ser una molestia escribir un nuevo paquete para un pequeño fragmento de código como en el ejemplo. Lo que puede hacer en su lugar es exportar el bloque de código, exportar una función de “ayuda” que comstack el código fuente y ejecuta el helper. Eso hará que la función CXX esté disponible, luego use otra función auxiliar para llamarla. Por ejemplo:

 # Snow must still be installed, but this functionality is now in "parallel" which ships with base r. library(parallel) # Keep your source as an object src1 <- ' Rcpp::NumericMatrix xbem(xbe); int nrows = xbem.nrow(); Rcpp::NumericVector gv(g); for (int i = 1; i < nrows; i++) { xbem(i,_) = xbem(i-1,_) * gv[0] + xbem(i,_); } return xbem; ' # Save the signature sig <- signature(xbe = "numeric", g="numeric") # make a function that compiles the source, then assigns the compiled function # to the global environment c.inline <- function(name, sig, src){ library(Rcpp) funCXX <- inline::cxxfunction(sig = sig, body = src, plugin="Rcpp") assign(name, funCXX, envir=.GlobalEnv) } # and the function which retrieves and calls this newly-compiled function c.namecall <- function(name,...){ funCXX <- get(name) funCXX(...) } # Keep your example matrix A <- matrix(rnorm(400), 20,20) # What are we calling the compiled funciton? fxname <- "TestCXX" ## Parallel cl <- makeCluster(2, type = "PSOCK") # Export all the pieces clusterExport(cl, c("src1","c.inline","A","fxname")) # Call the compiler function clusterCall(cl, c.inline, name=fxname, sig=sig, src=src1) # Notice how the function now named "TestCXX" is available in the environment # of every node? clusterCall(cl, ls, envir=.GlobalEnv) # Call the function through our wrapper clusterCall(cl, c.namecall, name=fxname, A, 0.5) # Works with my testing 

He escrito un paquete ctools (autopromoción desvergonzada) que envuelve una gran parte de la funcionalidad que está en los paquetes paralelos y Rhpc para computación en clúster, ambos con PSOCK y MPI. Ya tengo una función llamada "c.sourceCpp" que llama "Rcpp :: sourceCpp" en cada nodo de forma muy parecida a la anterior. Voy a agregar un "c.inlineCpp" que hace lo anterior ahora que veo la utilidad de esto.

Editar:

A la luz de los comentarios de Coatless, la Rcpp::cppFunction() de hecho niega la necesidad del ayudante c.inline aquí, aunque todavía se necesita el c.namecall .

 src2 <- ' NumericMatrix TestCpp(NumericMatrix xbe, int g){ NumericMatrix xbem(xbe); int nrows = xbem.nrow(); NumericVector gv(g); for (int i = 1; i < nrows; i++) { xbem(i,_) = xbem(i-1,_) * gv[0] + xbem(i,_); } return xbem; } ' clusterCall(cl, Rcpp::cppFunction, code=src2, env=.GlobalEnv) # Call the function through our wrapper clusterCall(cl, c.namecall, name="TestCpp", A, 0.5) 
Intereting Posts