снег, inline & Rcpp:
2520 просмотра
3 ответа
Я написал функцию Rcpp
и скомпилировал ее inline
. Теперь я хочу запустить его параллельно на разных ядрах, но получаю странную ошибку. Вот минимальный пример, где функция funCPP1
может быть собрана и работает хорошо само по себе, но не может быть вызвана snow
«ы clusterCall
функции. Функция хорошо работает как отдельный процесс, но выдает следующую ошибку при параллельном запуске:
Error in checkForRemoteErrors(lapply(cl, recvResult)) :
2 nodes produced errors; first error: NULL value passed as symbol address
А вот код:
## 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)
Автор: Vincent
Источник
Размещён: 17.05.2019 02:40
Ответы (3)
15 плюса
Продумайте это - что делает inline? Он создает функцию C / C ++ для вас, затем компилирует и связывает ее в динамически загружаемую разделяемую библиотеку. Где тот сидит? Во временном каталоге R
Итак, вы попробовали правильно, отправив интерфейс R, вызывающий эту разделяемую библиотеку, в другой процесс (у которого есть другой временный каталог !!), но он не получает файл dll / so.
Следовательно, совет состоит в том, чтобы создать локальный пакет, установить его и запустить как снежный процесс, так и вызвать его.
(И как всегда: ответы лучшего качества можно найти в списке rcpp-devel, который читают больше участников Rcpp, чем SO).
Автор: Dirk Eddelbuettel Размещён: 20.05.2011 03:470 плюса
Старый вопрос, но я наткнулся на него, просматривая верхние теги Rcpp, так что, возможно, этот ответ будет по-прежнему полезен.
Я думаю, что ответ Дирка верен, когда код, который вы написали, полностью очищен от ошибок и делает то, что вы хотите, но это может быть затруднительно, чтобы написать новый пакет для такого небольшого фрагмента кода, как в примере. Вместо этого вы можете экспортировать блок кода, экспортировать функцию «помощник», которая компилирует исходный код и запускает помощник. Это сделает функцию CXX доступной, а затем использует другую вспомогательную функцию для ее вызова. Например:
# 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
Я написал пакет ctools (бесстыдное самореклама), который включает в себя множество функциональных возможностей параллельных пакетов и пакетов Rhpc для кластерных вычислений, как с PSOCK, так и с MPI. У меня уже есть функция с именем «c.sourceCpp», которая вызывает «Rcpp :: sourceCpp» на каждом узле почти так же, как и выше. Я собираюсь добавить в «c.inlineCpp», который делает выше, теперь, когда я вижу его полезность.
Редактировать:
В свете комментариев Coatless, на Rcpp::cppFunction()
самом деле отрицает необходимость c.inline
помощника здесь, хотя 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)
Автор: Brian Albert Monroe
Размещён: 05.09.2016 03:45
0 плюса
Я решил это путем поиска на каждом узле кластера кластера файла R с нужной встроенной функцией C:
clusterEvalQ(cl,
{
library(inline)
invisible(source("your_C_func.R"))
})
И ваш файл your_C_func.R должен содержать определение функции C:
c_func <- cfunction(...)
Автор: Cristina Bazzano
Размещён: 22.03.2019 09:38
Вопросы из категории :
- r Как получить доступ к последнему значению в векторе?
- r Пакеты оптимизации для R
- r Есть ли у R такие операторские операции, как Perl qw ()?
- r Библиотека / инструмент для рисования тройных / треугольных графиков
- r Участки без заголовков / надписей в R
- r Расчет скользящей средней
- rcpp снег, inline & Rcpp:
- rcpp RCPP передать по ссылке против по значению
- rcpp Указанный модуль не может быть найден в R
- rcpp Ошибка в loadNamespace (name): нет пакета с именем 'Rcpp'
- rcpp Индексный элемент из списка в Rcpp
- rcpp Ошибка в loadNamespace (name): нет пакета с именем 'RInside'
- snow Ошибка вызова функции сериализации R
- snow Инициализация кластера MPI с использованием Rmpi
- snow R Snow Rlecuyer: применить функцию с временным посевным материалом
- snow Регрессии с использованием параллельных / многоядерных процессов
- snow R foreach: от одного компьютера к кластеру