如何在HPC集群3个节点各用20核并行运行R代码?
多节点HPC上R并行计算的核数利用问题解决
1. HPC节点详情
当前可用3个节点,每个节点的硬件参数如下(scontrol show node输出):
scontrol show node Arch=x86_64 CoresPerSocket=10 CPUAlloc=20 CPUTot=20 CPULoad=22.67 AvailableFeatures=(null) ActiveFeatures=(null) Gres=(null) . . RealMemory=91000 AllocMem=0 FreeMem=77291 Sockets=2 Boards=1 State=ALLOCATED ThreadsPerCore=1 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A Partitions=cpu_normal_q BootTime=2023-10-20T12:56:13 SlurmdStartTime=2023-10-20T12:57:43 CfgTRES=cpu=20,mem=91000M,billing=20 AllocTRES=cpu=20 CapWatts=n/a CurrentWatts=0 AveWatts=0 ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
每个节点总计20核,目标是3个节点共使用60核运行并行任务。
2. 原并行计算代码
使用doParallel实现矩阵运算并行迭代的R代码:
library(doParallel) library(Matrix) # 原代码用detectCores()仅能获取当前节点核数,无法跨节点 num_cores <- detectCores() # 初始化并行后端 cl <- makeCluster(num_cores) # 注册集群 registerDoParallel(cl) # 获取当前使用核数 cores_utilized <- getDoParWorkers() # 矩阵乘与求逆函数 matrix_mult_inv <- function() { mat <- matrix(rnorm(10000), nrow = 100) result <- mat %*% mat inv_result <- solve(result) return(inv_result) } start_time <- Sys.time() # 300次并行迭代,结果写入文件 result <- foreach(i = 1:300, .combine = cbind) %dopar% { write.table(matrix_mult_inv(), paste("iteration_", i, ".txt", sep = "")) } end_time <- Sys.time() print(paste("Number of cores being utilized:", cores_utilized)) print(paste("Time taken:", end_time - start_time)) stopCluster(cl)
3. 遇到的问题
尝试用以下代码指定节点和核数时,实际仅利用了3核,无法达到60核的目标:
cl <- makeCluster(num_nodes, type = "SOCK", explicit = TRUE, outfile = "", nodes = c(#3 specific node names input here#), cpus = cores_per_node)
4. 解决方案
4.1 正确创建跨节点并行集群
问题出在makeCluster的参数使用上:当需要跨节点分配指定核数时,需明确指定每个节点要启动的worker数量(即核数),而非仅指定节点数量。
修改集群初始化代码如下:
library(doParallel) library(Matrix) # 替换为实际的3个节点名称 node_names <- c("node01", "node02", "node03") # 每个节点分配20个worker,生成包含60个元素的节点列表(每个节点名重复20次) spec <- unlist(lapply(node_names, function(node) rep(node, 20))) # 创建跨节点SOCK集群,outfile=""用于捕获worker输出 cl <- makeCluster(spec, type = "SOCK", outfile = "") # 注册集群 registerDoParallel(cl) # 验证核数,此时应返回60 cores_utilized <- getDoParWorkers() # 后续函数定义、迭代逻辑与原代码一致 matrix_mult_inv <- function() { mat <- matrix(rnorm(10000), nrow = 100) result <- mat %*% mat inv_result <- solve(result) return(inv_result) } start_time <- Sys.time() # 注意:原代码中.combine=cbind无实际意义(write.table返回NULL),可改为.combine=list或省略 result <- foreach(i = 1:300) %dopar% { write.table(matrix_mult_inv(), paste("iteration_", i, ".txt", sep = "")) } end_time <- Sys.time() print(paste("Number of cores being utilized:", cores_utilized)) print(paste("Time taken:", end_time - start_time)) stopCluster(cl)
4.2 关键注意事项
- 包依赖:确保所有目标节点上都已安装
doParallel和Matrix包,否则worker会报错。 - SSH无密码访问:HPC集群通常已配置节点间免密SSH,但如果未配置,需提前完成密钥对设置,确保主节点能无密码登录其他节点。
- 资源分配:确认3个节点的20核均未被其他任务占用(可通过
squeue或scontrol show node再次核对CPUAlloc状态)。
内容的提问来源于stack exchange,提问作者Arnoneel Sinha
相关产品推荐
相关产品推荐

