неправильные выходные размеры при разделении вектора для параллельной выборки в R - PullRequest
0 голосов
/ 10 июня 2019

В Windows (еще предстоит тестирование в Linux) я пытаюсь (смущающе) распараллелить байесовскую выборку для больших групп населения.Я запускаю несколько тестов и обнаружил довольно симпатичное поведение при обработке списка, в котором объекты списка имеют разную длину.Используются следующие библиотеки: parallel, snow, doSNOW, foreach и rlecuyer.

## Set parameters
cores<-4; N<-10004; Mean<-rnorm(N,sd=0.7); SD<-rnorm(N,mean=1,sd=0.1)

## Split the population
lst<-suppressWarnings(split(1:N,f=1:cores))

## Initialize cluster
cl <<- parallel::makePSOCKcluster(cores)
parallel::clusterSetRNGStream(cl, iseed = round(runif(cores)*1001))

## Export and run test
clusterExport(cl,c("lst"))
system.time(
  theta<-as.vector(parSapply(cl,1:cores,function(x) rnorm(length(lst[[x]]),mean=Mean[lst[[x]]],sd=SD)))
)

## validate length
system.time(
  n.lst<-as.vector(parSapply(cl,1:cores,function(x) lst[[x]]))
)
## Stop the cluster and check data
parallel::stopCluster(cl)
length(theta)  # 10004
length(n.lst)  # 10004

Теперь я изменяю численность населения на число, НЕ делимое на 4

## Set parameters
cores<-4; N<-10001; Mean<-rnorm(N,sd=0.7); SD<-rnorm(N,mean=1,sd=0.1)

## Run the same code above... And check the output arrays:
length(theta)  # 25010000
length(n.lst)  # 25010000

Так что да, список экспоненциально увеличился ... до длины массива, которая НЕ 2500 + 2500 + 2500 + 2501, а вместо этого 2500 *2501* 4 ... что для меня не имеет смысла.

1 Ответ

0 голосов
/ 18 июня 2019

Оказывается, проблема должна быть связана с использованием parSapply; Мне пришлось преобразовать проблему в parLapply, и я наконец получил приемлемые результаты. При перекодировании проблемы следующим образом все получилось. Примечание: мне пришлось уйти от split, так как не было никакого очевидного способа предотвратить запуск модуля по индексам, которые он разделяет. Вместо этого я создал функцию, которая разделяет вектор последовательно.

vsplit<-function(x,f) {
  setNames(lapply(f,function (y) x[ceiling((1:length(x))/(length(x)/max(f)))==y]),f)
}
PNorm<-function(x) {
  rnorm(length(lt[[x]]),lt[[x]],1)
}
settings<-list(); cores<-settings$cores<-4; N<-10000001
Mean<-rnorm(N,sd=0.7)
SD<-1
lt<-suppressWarnings(vsplit(Mean,1:cores))
cl <<- parallel::makePSOCKcluster(settings$cores)
parallel::clusterSetRNGStream(cl, iseed = round(runif(settings$cores)*1001))
clusterExport(cl,c("lt"))
system.time(
  that<-unlist(parLapply(cl,1:cores,PNorm))
)
length(that)
parallel::stopCluster(cl)
...