Параллельная версия преобразования (или изменения) в R?

#r #parallel-processing

#r #параллельная обработка

Вопрос:

У меня есть медленная функция, которую я хочу применить к каждой строке в data.frame. Вычисления смущающе параллельны.

У меня 4 ядра, но встроенные функции R используют только одно.

Все, что я хочу сделать, это параллельный эквивалент:

 data$c = slow.foo(data$a, data$b)
 

Я не могу найти четких инструкций о том, какую библиотеку использовать (перегружен выбором) и как ее использовать. Буду признателен за любую помощь.

Ответ №1:

parallel Пакет включен в базовый R. Вот краткий пример использования parApply из этого пакета:

 library(parallel)

# Some dummy data
d <- data.frame(x1=runif(1000), x2=runif(1000))

# Create a cluster with 1 fewer cores than are available. Adjust as necessary
cl <- makeCluster(detectCores() - 1)

# Just like regular apply, but rows get sent to the various processes
out <- parApply(cl, d, 1, function(x) x[1] - x[2])

stopCluster(cl)

# Same as x1 - x2?
identical(out, d$x1 - d$x2)

# [1] TRUE
 

У вас также есть, например, parSapply и parLapply в вашем распоряжении.

Конечно, для примера, который я привел, векторизованная операция d$x1 - d$x2 выполняется намного быстрее. Подумайте, можно ли векторизовать ваши процессы, а не выполнять построчно.

Комментарии:

1. Спасибо за информацию. Ваш пример работает, но я не могу получить именованный эквивалент для работы. Я изменил x[1]-x[2] на x$x1-x$x2 . Это приводит к следующей ошибке: Error in checkForRemoteErrors(val) : 7 nodes produced errors; first error: $ operator is invalid for atomic vectors

2. @sharoz: Это потому, что строки упрощены до векторов (для которых $ подмножество не является опцией). То же самое произойдет и для непараллельного apply(d, 1, function(x) x$x1 - x$x2) . Если вы хотите использовать имена, вы можете сделать: function(x) x['x1'] - x['x2'] .

3. Еще раз спасибо, но это вызывает проблемы с именованными переменными. В исходном примере я определил bar <- function(x) slow.foo(x['a'], x['b']) . Затем я запустил parApply(cl, d, 1, bar) который не может найти символ slow.foo (хотя он определен). Есть идеи?

4. @sharoz: Помимо объекта, который вы передаете parApply (т.Е. d ), Вам необходимо отправлять объекты / функции в кластерные процессы clusterExport . Попробуйте: clusterExport(cl, 'slow.foo') до parApply . Этот символьный вектор должен также включать имена любых объектов, на которые ссылаются в теле slow.foo (кроме тех, которые передаются из bar ). Имейте в виду, что если какой-либо из указанных объектов огромен, вы можете столкнуться с проблемами с памятью, отправив копии всем процессам.