2017-11-29 11 views
4

내가 가질 수 있도록 위의 내가 (포크)을 병렬화 할 수있는 방법 purr::pmap어떻게 포크 /의 과정을 병렬화 purrr :: PMAP


library(tidyverse) 

set.seed(1) 
params <- tribble(
    ~mean, ~sd, ~n, 
    5,  1, 1, 
    10,  5, 3, 
    -3, 10, 5 
) 
params %>% 
    pmap(rnorm) 
#> [[1]] 
#> [1] 4.373546 
#> 
#> [[2]] 
#> [1] 10.918217 5.821857 17.976404 
#> 
#> [[3]] 
#> [1] 0.2950777 -11.2046838 1.8742905 4.3832471 2.7578135 

프로세스와 직렬 처리를 수행하는 다음 코드 더 빠르게 실행되고 동일한 결과가 생성됩니까?

여기서는 일러스트레이션 목적으로 rnorm을 사용합니다. 실제로는 무거운 작업을 수행하는 기능이 있습니다. 그것은 병렬 처리가 필요합니다.

rnorm 함수와 params 입력으로 동일한 결과를 산출하는 한 비침 해 (비단백) 솔루션을 사용할 수 있습니다.

+0

이인가 실제 기능 결정적? 그렇지 않으면 무작위성에도 재현성이 필요합니다. 각 반복의 결과는 이전 반복 이후의 RNG 상태에 따라 다릅니다. 미리 RNG 상태를 알 수있는 방법이 없다면 (예를 들어있는 것처럼 보입니다.)'.Random.seed '를 해킹 할 수는 있지만 ........ 추측 할 것입니다. –

+0

https : // stat의 6 장 참조 .ethz.ch/R-manual/R-devel/library/parallel/doc/parallel.pdf –

+0

좀 더 현실적인 예를 제시 할 수 있습니까? 매개 변수의 수 ('nrow (params)')가 높거나 시뮬레이션 수가'n '입니까? –

답변

4

요약하면 pmap()과 비슷한 구문을 허용하는 "병렬 pmap()"은 lift(mcmapply)() 또는 lift(clusterMap)()과 같이 보일 수 있습니다. Windows에서하지 않은 경우


, 당신은 할 수 :

:

library(parallel) 

# forking 

set.seed(1, "L'Ecuyer") 
params %>% 
    lift(mcmapply, mc.cores = detectCores() - 1)(FUN = rnorm) 

# [[1]] 
# [1] 4.514604 
# 
# [[2]] 
# [1] 0.7022156 0.8734875 5.0250478 
# 
# [[3]] 
# [1] 8.7704060 11.7217925 -12.8776289 -10.7466152 0.5177089 

편집 여기

는 더 pmap를 사용하여 같은 느낌해야 "청소기"옵션입니다

nc <- max(parallel::detectCores() - 1, 1L) 

par_pmap <- function(.l, .f, ..., mc.cores = getOption("mc.cores", 2L)) { 
    do.call(
    parallel::mcmapply, 
    c(.l, list(FUN = .f, MoreArgs = list(...), SIMPLIFY = FALSE, mc.cores = mc.cores)) 
) 
} 

f <- function(n, mean, sd, ...) rnorm(n, mean, sd) 

params %>% 
    par_pmap(f, some_other_arg_to_f = "foo", mc.cores = nc) 

당신이 윈도우 (또는 다른 OS)의 경우

, 당신은 할 수 : 당신이 foreach를 사용하는 경향이있어 경우

library(parallel) 

# (Parallel SOCKet cluster) 

cl <- makeCluster(detectCores() - 1) 

clusterSetRNGStream(cl, 1) 
params %>% 
    lift(clusterMap, cl = cl)(fun = rnorm) 

# [[1]] 
# [1] 5.460811 
# 
# [[2]] 
# [1] 7.573021 6.870994 5.633097 
# 
# [[3]] 
# [1] -21.595569 -21.253025 -12.949904 -4.817278 -7.650049 

stopCluster(cl) 

, 당신은 할 수 :

library(doParallel) 

# (fork by default on my Linux machine, should PSOCK by default on Windows) 

registerDoParallel(cores = detectCores() - 1) 

set.seed(1, "L'Ecuyer") 
lift(foreach)(params) %dopar% 
    rnorm(n, mean, sd) 

# [[1]] 
# [1] 4.514604 
# 
# [[2]] 
# [1] 0.7022156 0.8734875 5.0250478 
# 
# [[3]] 
# [1] 8.7704060 11.7217925 -12.8776289 -10.7466152 0.5177089 

stopImplicitCluster() 
+0

정말 고마워요, 당신의 접근 방식과 관련된 또 다른 문제가 있습니다. 너 좀 봐 줄래? https://stackoverflow.com/questions/47625279/how-to-preserve-the-list-of-data-frame-form-after-using-parallel-apply – neversaint