python与MPI(mpi4py)问题,客户端无法连接

1 投票
2 回答
3172 浏览
提问于 2025-04-16 18:37

我遇到的错误是:

追踪信息(最近的调用在最前面): 文件 "client2.py",第 14 行,在 port = MPI.Lookup_name(service, info) 文件 "Comm.pyx",第 1676 行,在 mpi4py.MPI.Lookup_name (src/mpi4py.MPI.c:64562) mpi4py.MPI.Exception: MPI_ERR_NAME: 名称参数无效

我正在尝试使用 mpi4py 实现客户端/服务器模型。服务器可以发布名称并等待客户端连接。然而,客户端无法使用下面 API 中描述的必要方法:

#! /usr/bin/env python

from mpi4py import MPI

rank = MPI.COMM_WORLD.Get_rank()

def log(msg, *args):
    if rank == 0:
        print msg % args

info = MPI.INFO_NULL
service = 'pyeval'
log("looking-up service '%s'", service)
port = MPI.Lookup_name(service, info) // PROBLEM HERE !
log("service located  at port '%s'", port)

root = 0
log('waiting for server connection...')
comm = MPI.COMM_WORLD.Connect(port, info, root)
log('server connected...')

while True:
    done = False
    if rank == root:
        try:
            message = raw_input('pyeval>>> ')
            if message == 'quit':
                message = None
                done = True
        except EOFError:
            message = None
            done = True
        comm.Send(message, dest=0, tag=0)
   else:
        message = None
    done = MPI.COMM_WORLD.Bcast(done, root)
    if done:
        break

log('disconnecting server...')
comm.Disconnect()

我也会发布服务器端的代码,因为这可能会有所帮助:

#! /usr/bin/env python

from mpi4py import MPI

rank = MPI.COMM_WORLD.Get_rank()

def log(msg, *args):
    if rank == 0:
        print msg % args


log('')

info = MPI.INFO_NULL

port = MPI.Open_port(info)
log("opened port: '%s'", port)

service = 'pyeval'
MPI.Publish_name(service, info, port)
log("published service: '%s'", service)

root = 0
log('waiting for client connection...')
comm = MPI.COMM_WORLD.Accept(port, info, root)
log('client connected...')

while True:
    done = False
    if rank == root:
        message = comm.Recv(source=0, tag=0)
        if message is None:
            done = True
        else:
            try:
                print 'eval(%r) -> %r' % (message, eval(message))
            except StandardError:
                print "invalid expression: %s" % message
    done = MPI.COMM_WORLD.Bcast(done, root)
    if done:
        break

log('disconnecting client...')
comm.Disconnect()

log('upublishing service...')
MPI.Unpublish_name(service, info, port)

log('closing port...')
MPI.Close_port(port)

2 个回答

1

我需要用到ompi-server来发布名字和查找名字。下面是我执行服务器和客户端的步骤:

首先,启动ompi-server:

rm -f /tmp/ompi-server.txt
killall ompi-server
ompi-server -r /tmp/ompi-server.txt

然后,运行服务器:

mpiexec --ompi-server file:/tmp/ompi-server.txt -n 1 python server.py

最后,启动客户端:

mpiexec --ompi-server file:/tmp/ompi-server.txt -n 1 python client.py
2

你希望服务器能够启动客户端,这样它们就可以进行通信。此外,你的发送、接收和广播操作应该用小写字母来写,也就是send、recv和bcast。mpi4py支持大写和小写的写法,但大写的版本需要用“常规”的C/C++/Fortran参数,而小写的写法更符合Python的风格。

所以,以下代码在我这边运行得很成功——client.py:

#! /usr/bin/env python
from mpi4py import MPI

rank = MPI.COMM_WORLD.Get_rank()

def log(msg, *args):
    if rank == 0:
        print msg % args

info = MPI.INFO_NULL
service = "pyeval"
log("looking-up service '%s'", service)
port = MPI.Lookup_name(service)
log("service located  at port '%s'", port)

root = 0
log('waiting for server connection...')
comm = MPI.COMM_WORLD.Connect(port, info, root)
log('server connected...')

while True:
    done = False
    if rank == root:
        try:
            message = raw_input('pyeval>>> ')
            if message == 'quit':
                message = None
                done = True
        except EOFError:
            message = None
            done = True
        comm.send(message, dest=0, tag=0)
    else:
        message = None
    done = MPI.COMM_WORLD.bcast(done, root)
    if done:
        break

log('disconnecting server...')
comm.Disconnect()

还有server.py:

#! /usr/bin/env python

from mpi4py import MPI

rank = MPI.COMM_WORLD.Get_rank()

def log(msg, *args):
    if rank == 0:
        print msg % args

log('')

info = MPI.INFO_NULL

port = MPI.Open_port(info)
log("opened port: '%s'", port)

service = 'pyeval'
MPI.Publish_name(service, info, port)
log("published service: '%s'", service)

MPI.COMM_WORLD.Spawn("./client.py", maxprocs=1)

root = 0
log('waiting for client connection...')
comm = MPI.COMM_WORLD.Accept(port, info, root)
log('client connected...')

while True:
    done = False
    if rank == root:
        message = comm.recv(source=0, tag=0)
        if message is None:
            done = True
        else:
            try:
                print 'eval(%r) -> %r' % (message, eval(message))
            except StandardError:
                print "invalid expression: %s" % message
    done = MPI.COMM_WORLD.bcast(done, root)
    if done:
        break

log('disconnecting client...')
comm.Disconnect()

log('upublishing service...')
MPI.Unpublish_name(service, info, port)

log('closing port...')
MPI.Close_port(port)

不过,你还需要注意,大多数MPI的实现只会把标准输入(stdin)给到编号为0的进程,这样客户端就没有一个好的方式从终端获取输入(一般来说,如果有多个客户端,这样该怎么处理呢?)

撰写回答