大连人工智能计算平台——华为昇腾AI平台——高性能计算HPC的C语言运行环境及作业的配置

前文已对超算和平台进行了介绍,本文就不对基础知识进行介绍了。

 

 

============================================

 

需要运行的demo代码:

复制代码
#include "mpi.h"  
#include <stdio.h>  
#include <math.h>  
int main (int argc, char **argv)  
{  
int myid, numprocs;  
int namelen;  
char processor_name[MPI_MAX_PROCESSOR_NAME];  
MPI_Init (&argc, &argv);  
MPI_Comm_rank (MPI_COMM_WORLD, &myid);  
MPI_Comm_size (MPI_COMM_WORLD, &numprocs);  
MPI_Get_processor_name (processor_name, &namelen);  
fprintf (stderr, "Hello World! Process %d of %d on %s\n", myid, numprocs, processor_name);  
MPI_Finalize ();  
return 0;  
}
复制代码

 

 

 

 

编译:(这里我们选择在登录节点,也就是master节点进行编译,这样做主要是方便debug,实际上如果编译工作量较大可以考虑放在slave运算节点上进行编译)

编译命令:

复制代码
MPI_CC=/home/HPCBase/compiler/bisheng-compiler-2.1.0-aarch64-linux/bin
MPI_LIB=/home/HPCBase/HMPI/hmpi/lib/

export PATH=$MPI_CC:$PATH
export LD_LIBRARY_PATH=$MPI_LIB:$LD_LIBRARY_PATH



clang hello.c  -fPIC   -lmpi -o hello -I /home/HPCBase/HMPI/hmpi/include -L /home/HPCBase/HMPI/hmpi/lib/



chmod a+x hello
./hello
复制代码

 

 

 

=====================================================

 

 

代码编译好后我们需要编写作业书,并提交系统。一共有两种提交方式,第一种是在登录节点通过编写脚本然后通过命令dsub来提交系统;另一种是通过控制台可视化的填写作业参数。这里建议使用命令形式,毕竟可视化的操作每次运行都需要重新填写参数,不是很方便。

 

这里给出的事Hyper MPI的作业书:

(华为官方给出的帮助文档:https://support.huawei.com/enterprise/zh/doc/EDOC1100254476/8b901667

 

 

----------------------------------------------------------------------------

 

 

登录节点命令方式提交系统:

run.sh

复制代码
#!/bin/sh
echo ----- print env vars -----

if [ "${CCS_ALLOC_FILE}" != "" ]; then
    echo "   "
    ls -la ${CCS_ALLOC_FILE}
    echo ------ cat ${CCS_ALLOC_FILE}
    cat ${CCS_ALLOC_FILE}
fi

export HOSTFILE=/tmp/hostfile.$$
rm -rf $HOSTFILE
touch $HOSTFILE

# parse CCS_ALLOC_FILE
## node name,  cores, tasks, task_list
#  hpcbuild002 8 1 container_22_default_00001_e01_000002
#  hpctest005 8 1 container_22_default_00000_e01_000001

ntask=`cat ${CCS_ALLOC_FILE} | awk -v fff="$HOSTFILE" '{}
{
    split($0, a, " ")
    if (length(a[1]) >0 && length(a[3]) >0) {
        print a[1]" slots="a[2] >> fff
        total_task+=a[3]
    }
}END{print total_task}'`

echo "openmpi hostfile $HOSTFILE generated:"
echo "-----------------------"
cat $HOSTFILE
echo "-----------------------"
echo "Total tasks is $ntask"
echo "mpirun -hostfile $HOSTFILE -n $ntask <your application>"

#start a simple mpi program
#/usr/local/bin/mpirun -hostfile $HOSTFILE -n $ntask hostname

/home/HPCBase/HMPI/hmpi/bin/mpirun -hostfile $HOSTFILE -np $ntask --mca plm_rsh_agent /opt/batch/agent/tools/dstart /home/share/xxxxxxxxxxxxxxx/home/xxxxxx/xxxxxx/hello
ret=$?

rm -rf $HOSTFILE
exit $ret
复制代码

 

 

 

更改脚本权限:

chmod a+x ./run.sh

 

 

 

编写好脚本后使用dsub命令进行提交:

/opt/batch/cli/bin/dsub -n task_test -A xxxxxxxxxxxxx  --job_type hmpi -N 2000 -eo error.txt -oo output.txt /home/share/xxxxxxxxxx/home/xxxxxx/xxxxxx/run.sh

 

 

 

 

 

从控制台查看刚才运行的JOBID 5729 任务运行情况:

 

 

 

查看运行后的结果:

 

 

 

 可以看到运行结果,运行成功。

 

 

----------------------------------------------------------------------------

 

 

 

控制台可视化填写作业参数并提交系统:

 

 

单机运行的作业填写:

 

运行命令:

/home/HPCBase/HMPI/hmpi/bin/mpirun   -np 20  /home/share/xxxxxxxxxxxxxxx/home/xxxxxx/xxxxxx/hello

 

需要注意的是在单机运行模式下不受作业中的任务资源参数所限制,作业模板中的资源限制只为分布式运行模式下生成hostfile所用。但是单机模式下也受具体运行的slave服务器的具体内存和CPU数限制。在MPI程序中,如果MPI框架在安装的时候没有开启多线程模式的情况下,单机同时运行的进程数不能超过所在机器的逻辑CPU个数,因此在单机模式下 -np 后面的数值最大不能超过128,因为这个slave单机服务器的逻辑CPU个数为128,但是在实际运行过程中由于所在的slave服务器的算力不足可能导致过高的进程数会运行失败。该种方式运行只有凑巧作业调度分配的服务器有足够资源运行才能保证正常运行。

 

从正确的使用超算的方式上来说压根就没有单机运行模式这一说法,单机运行模式只在不使用作业调度的情况下存在。由于计算平台都是使用调度器的,因此就不存在真正意义上的单机运行模式,这里所说的单机运行模式其实是一种hacker方式,因为该种操作对于调度器来说它是不会识别 -np 后的进程数的,这是一种欺骗调度器的操作,因此该种方式运行对于调度器来说是按照单进程的运行需求进行调度的,但是实际上 -np 后面跟着的是一个较大的数(接近128),那么也会导致运行的进程因为运算资源不足导致运行失败,因此这里所说的单机运行模式并不建议实际操作中使用,这里介绍这种方式只为教学。

 

 

 

 

 

ps: 在分布式运行的情况下(不是这里的单机模式),可视化填写作业和命令模式提交作业一样都有默认的限制资源,这里的CPU和内存限制是指在运行时单机同一时间点最多可同时分配的CPU和单进程最多可用的内存,满足CPU限制和内存限制才会调度运行,不满足则会一直排队等待,如果进程运行过程中超出内存限制则会报错。不过需要注意的是如果作业中单机同时运行的CPU限制数超过slave物理机的单机逻辑CPU数时会导致永远无法满足条件,从而使该任务被调度器永久的排队等待所阻塞,这里不得不说的是华为的这个调度器有一定逻辑上的不足,在作业中单机CPU限制数高于物理机实际CPU数的同时如果总的任务数小于这个限制数其实也是可以运行的,比如限制单机最高999 CPU,实际单机128 CPU,而实际运行的进程为10,那么其实也是可以运行的,而这个调度器则会因为限制数高于物理机CPU总数而一直阻塞;同理,在分配单个进程的时候如果内存限制数高于某slave物理机的可用内存则不考虑该slave主机。

 

简单的来说,这个CPU限制数和内存限制数都是为生成hostfile文件所存在的,因此即使满足这个CPU和内存限制数也并不一定保证运行过程中资源满足。由于CPU数是好控制的,因此运行过程中这个CPU数是可以得到保证的,但是如果平台负载较重或网络负载较重也会有可能导致运行超时而报错;因为调度器只在分配内存是会考虑这个内存限制数,那么在运行过程中的内存不足也是无法限制的,比如内存限制数为4G,分配的slave主机有5G空闲内存,进程成功分配启动后运行过程中需要申请占用6G内存,那么也会动作资源不足而报错;更有可能的情况是内存限制数为4G,分配的slave主机有8G空闲内存,进程成功分配启动后运行过程中A进程先申请占用2G内存,但是此时另有B进程申请5G内存,此时物理内存只剩1G内存,而此时最初的A进程申请剩下的2G内存则会报错,导致运行失败。

 

 

对于调度器调度CPU和内存限制数,虽然有默认设置,但是实际运行过程中还是需要手动进行一定设置的。如果任务的 -np 100,A 主机空闲50 CPU,B主机空闲30 CPU,C主机空闲 20 CPU,D主机空闲 20 CPU,E主机空闲100 CPU,如果CPU限制数设置为10,那么这个任务就会被分配A主机10 CPU,B主机10 CPU,C主机10 CPU,D主机10 CPU,E主机10 CPU,如果像本文前面给出的代码,各个进程之间是不进行通信和等待的,那么这50个已分配的进程运行结束后才会再对另外50个进程进行分配,但是大多数代码都是进程之间需要进行通信和等待的,那么这样代码就会一直限制运行中,实际上是被阻塞了,形成了一种类似死锁的情况;如果设置CPU 限制数为20,那么5台主机各分配20个进程,该代码可以正常运行下去;如果设置进程数为30,那么E主机分配30 CPU,A主机分配30 CPU,B主机分配30 CPU,C主机分配30 CPU,D主机则不进行CPU分配;如果CPU限制数设置为50,那么A主机分配50 CPU,E主机分配50 CPU;如果CPU限制数设置为100,那么只对E主机分配100 CPU,其他主机不分配CPU。可以看到这个CPU限制数和内存限制数不仅对运行性能有影响,同时如果设置不当还会导致任务无法运行。

CPU限制数也不是在满足物理机限制的条件下越大越好的,比如上面的例子,此时如果把CPU限制数设置为大于100,那么同样会导致调度器无法分配CPU而造成任务阻塞;那么是不是越小越好呢,也不是,同样还是上面的例子,如果任务中进程需要通信和同步,那么如果把CPU限制数设置为小于20,则会导致部分CPU被分配,另一部分CPU被一直阻塞,形成一种类似死锁的情况。所以CPU限制数还是需要看情况进行考虑的,至于如何设置则需要看具体的任务,如果实在拿不准那就多试试。

 

 

 

 

================================

 

 

分布式模式下的作业填写:

经过长时间的研究发现现有的所提供的可视化作业模板是不支持分布式作业的,因此如果需要使用分布式运行MPI需要使用命令模式。
 
 
 

================================

 
 
 
 

 

posted on   Angry_Panda  阅读(133)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-06-04 【转载】 模型融合
2017-06-04 matplotlib.pyplot中add_subplot方法参数111的含义
2017-06-04 转载:(论文) 二次指数平滑法中确定初始值的简便方法

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示