如何在 R 中进行并行化 k-means?

How to do parallelization k-means in R?

我有一个非常大的数据集 (5000*100),我想使用 kmeans 函数来查找聚类。但是,我不知道如何使用clusterApply函数。

set.seed(88)
mydata=rnorm(5000*100)
mydata=matrix(data=mydata,nrow = 5000,ncol = 100)

parallel.a=function(i) {
kmeans(mydata,3,nstart = i,iter.max = 1000)
} 

library(parallel)
cl.cores <- detectCores()-1
cl <- makeCluster(cl.cores)
clusterSetRNGStream(cl,iseed=1234)
fit.km = clusterApply(cl,x,fun=parallel.a(500))
stopCluster(cl)

clusterApply 需要 'x' 值,我不知道如何设置。另外,clusterApplyparSapplyparLapply有什么区别?非常感谢。

这是一种使用 clusterApply 通过并行化 nstart 参数(假设它大于一个)来执行并行 kmeans 的方法:

library(parallel)
nw <- detectCores()
cl <- makeCluster(nw)
clusterSetRNGStream(cl, iseed=1234)
set.seed(88)
mydata <- matrix(rnorm(5000 * 100), nrow=5000, ncol=100)

# Parallelize over the "nstart" argument
nstart <- 100
# Create vector of length "nw" where sum(nstartv) == nstart
nstartv <- rep(ceiling(nstart / nw), nw)
results <- clusterApply(cl, nstartv,
        function(n, x) kmeans(x, 3, nstart=n, iter.max=1000),
        mydata)
# Pick the best result
i <- sapply(results, function(result) result$tot.withinss)
result <- results[[which.min(i)]]
print(result$tot.withinss)

人们通常将 mydata 输出给工人,但此示例将其作为附加参数传递给 clusterApply。这是有道理的(因为任务的数量等于工人的数量),效率稍微高一点(因为它有效地将导出与计算结合起来),并且避免在集群工人上创建全局变量(这有点多整齐的)。 (当然,如果您计划使用该数据集对工作人员执行更多计算,则导出更有意义。)

请注意,您可以根据需要使用 detectCores()-1 个工作人员,但在我的机器上进行的基准测试表明,使用 detectCores() 个工作人员时它的执行速度要快得多。我建议您在您的机器上对其进行基准测试,看看哪个更适合您。


至于不同并行函数之间的区别,clusterApplylapply的并行版本,它在单独的任务中处理x的每个值。 parLapplylapply 的并行版本,它将 x 拆分为每个集群 worker 只发送一个任务(这样效率更高)。 parSapply 调用 parLapply 但简化结果的方式与 sapply 简化调用 lapply.

的结果相同

clusterApply 对于并行 kmeans 有意义,因为您手动拆分 nstart 这样它只向每个集群工作人员发送一个任务,从而使 parLapply 变得不必要。