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

在超级计算机上从MPI程序获取各进程IP地址的方法

嘿,刚好能帮到你!你的MPI程序已经能正常输出进程rank了,要加上每个进程的IP地址其实不难——毕竟MPI本身没有直接提供获取IP的API,咱们得借助操作系统的工具或者系统调用来实现,下面给你两种实用的方案,适配超算的Linux环境:

方案一:通过Shell命令获取IP(纯Fortran实现)

这种方法不用额外写其他语言代码,直接在Fortran里调用Linux的系统命令来获取IP,适合快速实现。我们可以用hostname -I命令(或者更精准的IP筛选命令)获取节点IP,把输出临时存到文件里再读入程序:

program hello
    include 'mpif.h'
    integer my_pe_num, errcode, iostat
    character(len=256) :: ip_addr, hostname
    integer :: len_host

    call MPI_INIT(errcode)
    call MPI_COMM_RANK(MPI_COMM_WORLD, my_pe_num, errcode)

    ! 先获取当前节点的主机名(可选,但能辅助验证)
    call MPI_GET_PROCESSOR_NAME(hostname, len_host, errcode)
    hostname = hostname(1:len_host)  ! 截断多余的空格

    ! 执行shell命令把IP写入临时文件,每个进程用自己的rank命名文件避免冲突
    call execute_command_line('hostname -I > /tmp/ip_'//trim(str(my_pe_num))//'.txt', wait=.true.)
    
    ! 读取临时文件里的IP地址
    open(unit=10, file='/tmp/ip_'//trim(str(my_pe_num))//'.txt', status='old', iostat=iostat)
    if (iostat == 0) then
        read(10, '(A)') ip_addr
        close(10)
        ! 清理临时文件
        call execute_command_line('rm /tmp/ip_'//trim(str(my_pe_num))//'.txt', wait=.true.)
    else
        ip_addr = 'Unknown IP'
    end if

    ! 输出rank和IP
    print *, 'Hello from rank ', my_pe_num, ', IP address: ', trim(ip_addr)

    call MPI_FINALIZE(errcode)
contains
    ! 辅助函数:把整数转成字符串,用于命名临时文件
    function str(i) result(s)
        integer, intent(in) :: i
        character(len=20) :: s
        write(s, '(I0)') i
        s = adjustl(s)
    end function str
end program hello

说明

  • hostname -I会输出节点的所有IPv4地址,如果你需要特定网卡(比如以太网)的IP,可以替换命令为:ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1(根据超算节点的网卡名称调整,比如可能是ib0、enp0s3等)
  • 临时文件用进程rank命名,避免多个进程写同一个文件导致冲突
  • 这个方法依赖Linux的shell命令,超算环境一般都支持

方案二:通过C系统调用获取IP(混合编程,更高效)

如果觉得调用shell命令和临时文件不够高效,可以用C语言的getaddrinfo系统调用直接获取IP,然后在Fortran里调用这个C函数——这种方式不依赖外部命令,速度更快:

第一步:写C语言的IP获取函数(getip.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

void get_ip_address(char *ip, int max_len) {
    char hostname[256];
    struct addrinfo hints, *res, *p;
    int status;

    // 获取当前节点的主机名
    if (gethostname(hostname, sizeof(hostname)) != 0) {
        strncpy(ip, "Unknown Hostname", max_len);
        return;
    }

    // 设置addrinfo参数,只获取IPv4地址
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;    
    hints.ai_socktype = SOCK_STREAM;

    // 通过主机名获取地址信息
    if ((status = getaddrinfo(hostname, NULL, &hints, &res)) != 0) {
        strncpy(ip, gai_strerror(status), max_len);
        return;
    }

    // 遍历地址列表,取第一个IPv4地址
    for(p = res; p != NULL; p = p->ai_next) {
        char ipstr[INET_ADDRSTRLEN];
        inet_ntop(p->ai_family, &((struct sockaddr_in*)p->ai_addr)->sin_addr, ipstr, sizeof ipstr);
        strncpy(ip, ipstr, max_len);
        break;
    }

    freeaddrinfo(res);  // 释放内存
}

第二步:修改Fortran程序调用C函数

program hello
    include 'mpif.h'
    integer my_pe_num, errcode
    character(len=256) :: ip_addr

    ! 声明C函数的接口,让Fortran能调用它
    interface
        subroutine get_ip_address(ip, max_len) bind(C, name='get_ip_address')
            use, intrinsic :: iso_c_binding
            character(kind=c_char), intent(out) :: ip(*)
            integer(kind=c_int), intent(in) :: max_len
        end subroutine get_ip_address
    end interface

    call MPI_INIT(errcode)
    call MPI_COMM_RANK(MPI_COMM_WORLD, my_pe_num, errcode)

    ! 调用C函数获取IP地址
    call get_ip_address(ip_addr, len(ip_addr, kind=c_int))
    ! 去掉C字符串末尾的结束符,整理成Fortran可用的字符串
    ip_addr = trim(adjustl(ip_addr))

    ! 输出rank和IP
    print *, 'Hello from rank ', my_pe_num, ', IP address: ', trim(ip_addr)

    call MPI_FINALIZE(errcode)
end program hello

编译方法

用MPI编译器把Fortran和C代码一起编译:

mpif90 hello.f90 getip.c -o hello

说明

  • 这个方法直接调用系统API,性能更好,也不会产生临时文件
  • 代码里默认取第一个IPv4地址,如果需要其他类型的IP(比如IPv6),可以修改hints.ai_family为AF_INET6

两种方案都能在超算的批处理环境下正常运行,你可以根据自己的需求选择~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:04:42