【问题标题】:Test MPI on a cluster在集群上测试 MPI
【发布时间】:2010-01-31 02:40:22
【问题描述】:

我正在集群上学习 OpenMPI。这是我的第一个例子。我希望输出会显示来自不同节点的响应,但它们都来自同一个节点 node062。我只是想知道为什么以及如何实际从不同节点获取报告以显示 MPI 实际上正在将进程分发到不同节点?谢谢和问候!

ex1.c

/* test of MPI */  
#include "mpi.h"  
#include <stdio.h>  
#include <string.h>  

int main(int argc, char **argv)  
{  
char idstr[2232]; char buff[22128];  
char processor_name[MPI_MAX_PROCESSOR_NAME];  
int numprocs; int myid; int i; int namelen;  
MPI_Status stat;  

MPI_Init(&argc,&argv);  
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);  
MPI_Comm_rank(MPI_COMM_WORLD,&myid);  
MPI_Get_processor_name(processor_name, &namelen);  

if(myid == 0)  
{  
  printf("WE have %d processors\n", numprocs);  
  for(i=1;i<numprocs;i++)  
  {  
    sprintf(buff, "Hello %d", i);  
    MPI_Send(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD); }  
    for(i=1;i<numprocs;i++)  
    {  
      MPI_Recv(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD, &stat);  
      printf("%s\n", buff);  
    }  
}  
else  
{   
  MPI_Recv(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &stat);  
  sprintf(idstr, " Processor %d at node %s ", myid, processor_name);  
  strcat(buff, idstr);  
  strcat(buff, "reporting for duty\n");  
  MPI_Send(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD);  
}  
MPI_Finalize();  

}  

ex1.pbs

#!/bin/sh  
#  
#This is an example script example.sh  
#  
#These commands set up the Grid Environment for your job:  
#PBS -N ex1  
#PBS -l nodes=10:ppn=1,walltime=1:10:00  
#PBS -q dque    

# export OMP_NUM_THREADS=4  

 mpirun -np 10 /home/tim/courses/MPI/examples/ex1  

编译运行:

[tim@user1 examples]$ mpicc ./ex1.c -o ex1   
[tim@user1 examples]$ qsub ex1.pbs  
35540.mgt  
[tim@user1 examples]$ nano ex1.o35540  
----------------------------------------  
Begin PBS Prologue Sat Jan 30 21:28:03 EST 2010 1264904883  
Job ID:         35540.mgt  
Username:       tim  
Group:          Brown  
Nodes:          node062 node063 node169 node170 node171 node172 node174 node175  
node176 node177  
End PBS Prologue Sat Jan 30 21:28:03 EST 2010 1264904883  
----------------------------------------  
WE have 10 processors  
Hello 1 Processor 1 at node node062 reporting for duty  
Hello 2 Processor 2 at node node062 reporting for duty        
Hello 3 Processor 3 at node node062 reporting for duty        
Hello 4 Processor 4 at node node062 reporting for duty        
Hello 5 Processor 5 at node node062 reporting for duty        
Hello 6 Processor 6 at node node062 reporting for duty        
Hello 7 Processor 7 at node node062 reporting for duty        
Hello 8 Processor 8 at node node062 reporting for duty        
Hello 9 Processor 9 at node node062 reporting for duty  

----------------------------------------  
Begin PBS Epilogue Sat Jan 30 21:28:11 EST 2010 1264904891  
Job ID:         35540.mgt  
Username:       tim  
Group:          Brown  
Job Name:       ex1  
Session:        15533  
Limits:         neednodes=10:ppn=1,nodes=10:ppn=1,walltime=01:10:00  
Resources:      cput=00:00:00,mem=420kb,vmem=8216kb,walltime=00:00:03  
Queue:          dque  
Account:  
Nodes:  node062 node063 node169 node170 node171 node172 node174 node175 node176  
node177  
Killing leftovers...  

End PBS Epilogue Sat Jan 30 21:28:11 EST 2010 1264904891  
----------------------------------------

更新:

我想在一个 PBS 脚本中运行多个后台作业,以便这些作业可以同时运行。例如在上面的示例中,我添加了另一个调用来运行 ex1 并将两个运行都更改为 ex1.pbs 中的后台

#!/bin/sh  
#  
#This is an example script example.sh  
#  
#These commands set up the Grid Environment for your job:  
#PBS -N ex1  
#PBS -l nodes=10:ppn=1,walltime=1:10:00  
#PBS -q dque 

echo "The first job starts!"  
mpirun -np 5 --machinefile /home/tim/courses/MPI/examples/machinefile /home/tim/courses/MPI/examples/ex1 &  
echo "The first job ends!"  
echo "The second job starts!"  
mpirun -np 5 --machinefile /home/tim/courses/MPI/examples/machinefile /home/tim/courses/MPI/examples/ex1 &  
echo "The second job ends!" 

(1) qsub 将此脚本与之前编译的可执行文件 ex1 一起使用后,结果很好。

The first job starts!  
The first job ends!  
The second job starts!  
The second job ends!  
WE have 5 processors  
WE have 5 processors  
Hello 1 Processor 1 at node node063 reporting for duty        
Hello 2 Processor 2 at node node169 reporting for duty        
Hello 3 Processor 3 at node node170 reporting for duty        
Hello 1 Processor 1 at node node063 reporting for duty        
Hello 4 Processor 4 at node node171 reporting for duty        
Hello 2 Processor 2 at node node169 reporting for duty        
Hello 3 Processor 3 at node node170 reporting for duty        
Hello 4 Processor 4 at node node171 reporting for duty  

(2) 但是我觉得ex1的运行时间太快了,可能两个后台job没有太多的运行时间重叠,在我的实际项目中应用同样的方式时并非如此。所以我在 ex1.c 中添加了 sleep(30) 以延长 ex1 的运行时间,以便在后台运行 ex1 的两个作业几乎一直同时运行。

/* test of MPI */  
#include "mpi.h"  
#include <stdio.h>  
#include <string.h>  
#include <unistd.h>

int main(int argc, char **argv)  
{  
char idstr[2232]; char buff[22128];  
char processor_name[MPI_MAX_PROCESSOR_NAME];  
int numprocs; int myid; int i; int namelen;  
MPI_Status stat;  

MPI_Init(&argc,&argv);  
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);  
MPI_Comm_rank(MPI_COMM_WORLD,&myid);  
MPI_Get_processor_name(processor_name, &namelen);  

if(myid == 0)  
{  
  printf("WE have %d processors\n", numprocs);  
  for(i=1;i<numprocs;i++)  
  {  
    sprintf(buff, "Hello %d", i);  
    MPI_Send(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD); }  
    for(i=1;i<numprocs;i++)  
    {  
      MPI_Recv(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD, &stat);  
      printf("%s\n", buff);  
    }  
}  
else  
{   
  MPI_Recv(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &stat);  
  sprintf(idstr, " Processor %d at node %s ", myid, processor_name);  
  strcat(buff, idstr);  
  strcat(buff, "reporting for duty\n");  
  MPI_Send(buff, 128, MPI_CHAR, 0, 0, MPI_COMM_WORLD);  
}  

sleep(30); // new added to extend the running time
MPI_Finalize();  

}  

但是重新编译和再次qsub之后,结果好像不太对劲。有进程中止。 在 ex1.o35571 中:

The first job starts!  
The first job ends!  
The second job starts!  
The second job ends!  
WE have 5 processors  
WE have 5 processors  
Hello 1 Processor 1 at node node063 reporting for duty  
Hello 2 Processor 2 at node node169 reporting for duty  
Hello 3 Processor 3 at node node170 reporting for duty  
Hello 4 Processor 4 at node node171 reporting for duty  
Hello 1 Processor 1 at node node063 reporting for duty  
Hello 2 Processor 2 at node node169 reporting for duty  
Hello 3 Processor 3 at node node170 reporting for duty  
Hello 4 Processor 4 at node node171 reporting for duty  
4 additional processes aborted (not shown)  
4 additional processes aborted (not shown)  

在 ex1.e35571 中:

mpirun: killing job...  
mpirun noticed that job rank 0 with PID 25376 on node node062 exited on signal 15 (Terminated).  
mpirun: killing job...  
mpirun noticed that job rank 0 with PID 25377 on node node062 exited on signal 15 (Terminated).  

我想知道为什么有进程被中止?如何在 PBS 脚本中正确 qsub 后台作业?

【问题讨论】:

    标签: cluster-computing hpc openmpi pbs torque


    【解决方案1】:

    几件事: 你需要告诉 mpi 在哪里启动进程, 假设您使用的是 mpich,请查看 mpiexec 帮助部分并找到机器文件或等效描述。除非提供机器文件,否则它将在一台主机上运行

    PBS 自动创建节点文件。它的名称存储在 PBS 命令文件中可用的 PBS_NODEFILE 环境变量中。请尝试以下操作:

    mpiexec -machinefile $PBS_NODEFILE ...
    

    如果您使用的是 mpich2,您有两个使用 mpdboot 引导您的 mpi 运行时。我不记得命令的详细信息,您必须阅读手册页。记得创建秘密文件,否则 mpdboot 会失败。

    我又看了你的帖子,你会使用open mpi,你仍然需要为mpiexec命令提供机器文件,但你不必乱用mpdboot

    【讨论】:

    • 非常感谢!这解决了我的问题。如果其他人为自己保留了一些节点,或者一些节点现在正在运行其他作业,mpiexec 会以 $PBS_NODEFILE 作为机器文件提供吗?您还可以尝试回答我在superuser.com/questions/102812/torch-in-cluster 上发布的关于在集群上使用 PBS 的问题吗?提前致谢!
    【解决方案2】:

    默认情况下,PBS(我假设扭矩)以独占模式分配节点,因此每个节点只有一个作业。如果您有多个处理器,情况会有些不同,很可能每个 CPU 一个进程。 PBS 可以更改为以分时模式分配节点,请查看 qmgr.long 简而言之的手册页,很可能您在节点文件中不会有重叠节点,因为节点文件是在资源可用时创建的,而不是在提交。

    PBS 的目的是资源控制,最常见的是时间、节点分配(自动)。

    PBS 文件中的命令按顺序执行。您可以将进程置于后台,但这可能会破坏资源分配的目的,但我不知道您的确切工作流程。在主程序并行运行之前,我使用 PBS 脚本中的后台进程复制数据,使用 &。 PBS 脚本实际上只是一个 shell 脚本。

    您可以假设 PBS 对脚本的内部运作一无所知。您当然可以在 via 脚本中运行多个进程/线程。如果这样做,这取决于您和您的操作系统以平衡的方式分配核心/处理器。如果您使用的是多线程程序,最可能的方法是为节点运行一个 mpi 进程,然后生成 OpenMP 线程。

    如果您需要澄清,请告诉我

    【讨论】:

    • 再次感谢!在我的实际项目中,我想在单个 PBS 脚本中多次运行可执行文件,并且全部在后台运行。但是,当我在上面给出的简单示例中尝试这种方式时,有一些进程被中止。请参阅我对原始帖子的更新。如何在 PBS 脚本中运行后台作业?提前致谢!
    • @Tim 很难说,看起来 mpi 作业正在外部终止。你在 PBS 脚本中分配了多少时间,这是我的第一个猜测
    • walltime 设置为 1:10:00。我认为这对于使用 sleep(30) 运行来说已经足够长了。您认为在 PBS 脚本中指定后台作业有什么问题吗?
    • @Tim tim,可能不得不假设第一个 mpi 启动被第二个杀死。我对 OpenMPI 的了解比对 mpich 的了解少,但 OpenMPI 中的默认设置可能是每个节点只启动一个 mpi 实例.这是可以尝试的:拆分节点文件,以便 mpi 启动没有相同的节点。如果可行,请查看打开的 mpi 手册,了解如何在同一台机器上运行多个作业
    【解决方案3】:

    作为诊断,请尝试在调用 MPI_GET_PROCESSOR_NAME 后立即插入这些语句。

    printf("Hello, world.  I am %d of %d on %s\n", myid, numprocs, name);
    fflush(stdout); 
    

    如果所有进程都返回相同的节点 id,这将向我表明您不太了解作业管理系统和集群上发生的事情——也许 PBS 是(尽管您显然另有说明)将所有 10 个进程放在一个节点上(一个节点中有 10 个核心吗?)。

    如果这会产生不同的结果,这表明你的代码有问题,尽管在我看来它看起来不错。

    【讨论】:

    • 谢谢马克。我也不熟悉 PBS,现在也在学习它。如果可能的话,您能否尝试在superuser.com/questions/102812/torch-in-cluster 回答我关于 PBS/Torch 的问题?
    • 对不起,Tim,我是 Grid Engine 用户,对 PBS 的了解很模糊。
    【解决方案4】:

    您的代码中有一个与 mpich 无关的错误,您在两个循环中重用了 i。

    for(i=1;i<numprocs;i++)  
      {  
        sprintf(buff, "Hello %d", i);  
        MPI_Send(buff, 128, MPI_CHAR, i, 0, MPI_COMM_WORLD); }  
        for(i=1;i<numprocs;i++)  
    

    第二个 for 循环会搞砸。

    【讨论】:

      猜你喜欢
      • 2018-09-28
      • 2015-10-09
      • 2014-01-12
      • 1970-01-01
      • 2011-04-23
      • 2017-01-09
      • 2018-08-23
      • 2016-07-03
      • 2015-06-14
      相关资源
      最近更新 更多