如何迫使闲置的工人并行工作?

时间:2016-01-04 03:09:06

标签: r multithreading parallel-processing

我是新来发布的 - 我搜索过,找不到我的问题的答案。我在两台不同的机器上使用parallel软件包运行了以下R并行化代码(来自R blog上的Laptop CPU Usage)并获得了截然不同的处理时间结果。第一台机器是联想笔记本电脑,配备Windows 8,8GB RAM,Intel i7,2核/ 4逻辑处理器。第二台机器是戴尔台式机,Windows 7,16GB RAM,Intel i7,4核/ 8逻辑处理器。代码有时在第二台机器上运行得慢得多。我相信原因是第二台机器没有使用工作节点来完成任务。当我使用snow包中的函数snow.time()来检查节点使用情况时,第一台机器正在使用所有可用的工作人员来完成任务。但是,在功能更强大的机器上,它从不使用工作人员 - 整个任务由主人处理。为什么第一台机器使用工人,但第二台机器使用完全相同的代码?我如何“强迫”第二台机器使用可用的工作程序,以便代码真正并行化并且处理时间加快?这些答案对我正在做的其他工作有很大的帮助。提前致谢。函数snow.time()中的图表以及我使用的代码如下: PC CPU Usage RAII

runs <- 1e7
manyruns <- function(n) mean(unlist(lapply(X=1:(runs/4), FUN=onerun)))

library(parallel)
cores <- 4
cl <- makeCluster(cores)

# Send function to workers
tobeignored <- clusterEvalQ(cl, {
    onerun <- function(.){ # Function of no arguments
        doors <- 1:3
        prize.door <- sample(doors, size=1)
        choice <- sample(doors, size=1)
        if (choice==prize.door) return(0) else return(1) # Always switch
    }
    ; NULL
})

# Send runs to the workers
tobeignored <- clusterEvalQ(cl, {runs <- 1e7; NULL})
runtime <- snow.time(avg <- mean(unlist(clusterApply(cl=cl, x=rep(runs, 4), fun=manyruns))))
stopCluster(cl)

plot(runtime)

3 个答案:

答案 0 :(得分:5)

尝试使用clusterApplyLB代替clusterApply。 “LB”用于负载平衡。

非LB版本划分节点之间的任务数量并批量发送,但如果一个节点提前完成,则它将空闲等待其他节点。

LB版本向每个节点发送一个任务,然后监视节点,当节点完成时,它会向该节点发送另一个任务,直到分配完所有任务。如果每个任务的时间变化很大,那么效率会更高,但如果所有任务花费大约相同的时间,则效率会降低。

同时检查R和并行版本。如果我正确记住clusterApply函数在Windows机器上没有并行执行(但我不再看到那个注释,所以在最近的版本中可能已经补救了),所以区别可能是不同版本的并行包。 parLapply函数没有相同的问题,因此您可以重写代码以使用它,看看是否会产生影响。

答案 1 :(得分:1)

我不认为在从并行程序包中获取所有其他函数时,可以使用snow包中的snow.timing函数。 R 3.2.3中的并行源有一些用于计时的占位符代码,但它似乎不完整或与雪中的snow.timing函数兼容。我认为你仍会从clusterApply得到正确的结果,但snow.time返回的对象将等同于执行:

runtime <- snow.time(Sys.sleep(20))

如果您想使用snow.timing,我建议您只使用雪,尽管您仍然可以使用detectCores语法访问parallel::detectCores()等功能。

我真的不知道为什么你的脚本偶尔在台式机上运行缓慢,但我认为你并行化它的方式是合理和正确的。您可能希望在两台计算机上依次对manyruns进行基准测试,以排除两个系统上随机数生成代码的任何差异。但问题可能是系统服务导致整个系统变慢。

答案 2 :(得分:0)

我不能把代码放在评论中......我不太了解你的程序。你在创建什么样的集群?试试这个,将2e6调整为适合你的任何东西:

library(parallel)
library(Rmpi)
library(snow)
cl <- makeMPIcluster(3)
t <- system.time(parLapply(cl, 1:100, function(i) mean(rnorm(2e6))))
stopCluster(cl)
print(t)

对我来说,它运行10秒钟(2核心/超线程/ 5y旧笔记本电脑/ linux),所有4名工作人员都100%忙碌。您也可以尝试使用套接字群集。