2016-07-21 3 views
0

Я новичок в R и недавно вам нужно было найти индекс элементов в списке с определенными значениями. Я попытался ускорить операцию, используя foreach, а также сравнил два способа сделать это. В коде ниже «а» список и «Ь» является значением, чьи показатели мы хотим получить в «а»:простой пример R foreach

library("iterators") 
library("foreach") 
library("doParallel") 
a <- 1:200000 
b <- sample(1:200000,100000,replace=TRUE) 
registerDoParallel() 
getDoParWorkers(); #to see the number of cores 
system.time(unlist(lapply(b,function(x) which(a==x)))) 
system.time(foreach(i<-iter(b),.combine='c') %dopar% { which(a==b) }) 

выход:

Loading required package: parallel 
[1] 32 
    user system elapsed 
124.648 7.460 132.114 
    user system elapsed 
402.076 59.164 55.260 

Я задаюсь вопросом: 1) наивно, почему эта операция медленная? Я не проверял, но я думаю, что язык сценариев может сделать то же самое гораздо быстрее. 2) Не следует хорошо проводить масштаб операции параллельно, но все же кажется, что это займет больше времени, чем ожидалось, поскольку у меня есть 32 ядра. 3) на самом деле я повторяю строки матрицы, т. Е. Foreach (i < -iter (b, by = 'row'); comb = 'c')% dopar% {#stuff}. Я понимаю, что этот подход лучше, поскольку он не будет отправлять всю матрицу в каждое ядро. Есть ли способ подтвердить, проверяя, какие данные получают каждое ядро?

+0

Я не эксперт, поэтому я могу ошибаться, но: Я знаю, что, в общем, скомпилированные языки быстрее, чем интерпретируемые языки (на самом деле, как только вы скомпилировали, у вас есть исполняемый файл на машинке: язык сценария должны интерпретироваться каждый раз, что приводит к потере времени). Тогда векторизация в R полезна, несмотря на то, что она медленнее, чем другие языки ... но, по моему скромному мнению (я совершенно новичок в R), я теряю меньше времени в письменной форме в R, чем на скомпилированных не-векторных языках:) – Eugen

ответ

0

Вы делаете сравнения 1e5 * 2e5. Не удивительно, что это занимает некоторое время.

Каждый человек which(a==x) не так уж медленный, и у вас много накладных расходов на параллелизацию, если вы отправляете каждую итерацию отдельно рабочим. Было бы гораздо лучше отправить пучки итераций. В системе, отличной от Windows вы можете сделать это с mclapply:

a <- 1:20000 
b <- sample(1:20000,10000,replace=TRUE) 

library(parallel) 
system.time(res1 <- unlist(lapply(b,function(x) which(a==x)))) 
# user  system  elapsed 
#0.597  0.178  0.789 
system.time(res2 <- unlist(mclapply(b,function(x) which(a==x), 
            mc.preschedule = TRUE, mc.cores = 3))) 
# user  system  elapsed 
#0.004  0.022  0.325 
all.equal(res1, res2) 
#[1] TRUE 

Что касается 3): Там может быть лучше, чем способы распараллеливания (лучше бы матричная алгебра), но это зависит от вашего #stuff.

+0

спасибо, распараллеливание - это то, о чем я привык думать. – nak3c