You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Slurm环境下运行PCJ Java并行应用遇StartPoint未执行问题求助

在Slurm集群中运行PCJ Java并行应用的问题与解决方案

问题背景

在采用Slurm作为资源管理器的集群环境中运行基于PCJ的Java并行计算应用时,存在sbatch脚本、srun参数与Java代码的协调问题,PCJ自行启动从节点任务的逻辑可能与Slurm的启动流程冲突。提交指定2个从节点的sbatch脚本后,发现StartPoint接口的main()方法未执行,现提供基础可行示例及问题解决方法。


现有配置与输出

sbatch脚本

#!/bin/bash
#SBATCH -N 2                     # 节点数量
#SBATCH --ntasks-per-node 1      # 每个节点的任务数
#SBATCH --time=00:10:00          # 运行时长限制

srun -l java -jar test-pcj-slurm-0.0.1-SNAPSHOT.jar

Java代码

public class PcjSlurm implements StartPoint
{
    public static void main( String[] args )
    {
         String[] nodes = getStepNodes();
        System.out.println( "node name " + getNodeName() );
        if ( getNodeName().equals( "slave2" ) )
        {
            PCJ.executionBuilder( PcjSlurm.class ).addNodes( nodes ).start();
        }
        else
            System.out.println( "slave job" );
    }

    private static String[] getStepNodes() // 返回 ["slave1", "slave2"]
    {
        return System.getenv( "SLURM_STEP_NODELIST" ).split( "," );
    }

    private static String getNodeName()
    {
        return System.getenv( "SLURMD_NODENAME" );
    }

    // StartPoint 接口实现

    @Override
    public void main() throws Throwable
    {
        System.out.println( "PCJ id " + PCJ.myId() );
    }
}

运行输出(slurm-XXX.out)

1: node name slave1
1: slave job
0: node name slave2
0: 2024年3月4日 上午10:08:36 org.pcj.internal.InternalPCJ start
0: INFOS: PCJ version UNKNOWN

问题分析

  1. 启动流程冲突:Slurm的srun已在所有分配节点启动Java进程,代码中又调用PCJ.executionBuilder().addNodes(nodes).start()让PCJ重复启动从节点进程,导致PCJ的主从机制无法正常初始化,StartPoint的main()无法执行。
  2. 节点逻辑错误:仅指定slave2节点启动PCJ,未与Slurm分配的任务节点对齐,导致其他节点的进程仅执行了普通分支代码,未进入PCJ并行逻辑。

修正后的可行方案

方案1:复用Slurm启动的进程(推荐)

让PCJ直接使用Slurm通过srun启动的所有进程,无需手动启动从节点,通过系统参数传递集群配置。

修正后的sbatch脚本

#!/bin/bash
#SBATCH -N 2                     # 节点数量
#SBATCH --ntasks-per-node 1      # 每个节点的任务数
#SBATCH --time=00:10:00          # 运行时长限制

# 传递Slurm分配的节点列表给PCJ,指定主节点为第一个分配节点
srun -l java -Dpcj.nodes=$SLURM_STEP_NODELIST -Dpcj.master.node=$(scontrol show hostnames $SLURM_NODELIST | head -n1) -jar test-pcj-slurm-0.0.1-SNAPSHOT.jar

修正后的Java代码

import org.pcj.StartPoint;
import org.pcj.PCJ;

public class PcjSlurm implements StartPoint
{
    public static void main( String[] args )
    {
        // 直接初始化PCJ,使用系统参数传递的集群配置
        PCJ.executionBuilder(PcjSlurm.class).start();
    }

    @Override
    public void main() throws Throwable
    {
        System.out.println("节点: " + System.getenv("SLURMD_NODENAME") + " | PCJ id: " + PCJ.myId());
    }
}

方案2:仅主节点启动PCJ,由PCJ管理从节点

若需让PCJ自行启动从节点,需修改脚本仅在主节点运行Java进程,避免与Slurm的多进程启动逻辑冲突(需提前配置节点间免密SSH)。

修正后的sbatch脚本

#!/bin/bash
#SBATCH -N 2                     # 节点数量
#SBATCH --ntasks-per-node 1      # 每个节点的任务数
#SBATCH --time=00:10:00          # 运行时长限制

# 仅在Slurm分配的第一个主节点执行Java程序
MASTER_NODE=$(scontrol show hostnames $SLURM_NODELIST | head -n1)
if [ "$SLURMD_NODENAME" = "$MASTER_NODE" ]; then
    java -jar test-pcj-slurm-0.0.1-SNAPSHOT.jar
fi

修正后的Java代码

import org.pcj.StartPoint;
import org.pcj.PCJ;

public class PcjSlurm implements StartPoint
{
    public static void main( String[] args )
    {
        String[] nodes = System.getenv("SLURM_NODELIST").split(",");
        System.out.println("主节点: " + System.getenv("SLURMD_NODENAME"));
        // 启动PCJ并指定所有分配节点
        PCJ.executionBuilder(PcjSlurm.class).addNodes(nodes).start();
    }

    @Override
    public void main() throws Throwable
    {
        System.out.println("PCJ id " + PCJ.myId() + " 运行在节点: " + System.getenv("SLURMD_NODENAME"));
    }
}

验证说明

  • 方案1中,Slurm的srun会在每个分配节点启动一个Java进程,PCJ通过系统参数自动识别集群节点,StartPoint的main()会在所有节点上执行并行逻辑。
  • 方案2中,仅主节点启动Java进程,PCJ会通过SSH在其他节点启动从节点进程,适合需要自定义从节点启动逻辑的场景。

内容的提问来源于stack exchange,提问作者Fanfoue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 20:16:06