gpt4 book ai didi

sockets - 使用太多文件句柄打开 MPI 和 Boost MPI

转载 作者:行者123 更新时间:2023-12-03 11:50:13 25 4
gpt4 key购买 nike

我正在计算集群上使用 Boost MPI (1.55) 而不是 Open MPI (1.6.1) 运行一个项目。

我们的集群有具有 64 个 CPU 的节点,我们在每个节点上生成一个 MPI 进程。我们的大部分通信是在各个进程之间进行的,每个进程都有一系列 irecv() 请求打开(针对不同的标签)并使用 send() 阻塞执行发送。

我们遇到的问题是,经过很短的处理时间(通常不到 10 分钟),我们收到导致程序结束的错误:

[btl_tcp_component.c:1114:mca_btl_tcp_component_accept_handler] accept() failed: Too many open files in system (23).

更仔细的调试显示是网络套接字占用了这些文件句柄,并且我们正在达到操作系统打开的 65536 个文件句柄的限制。其中大部分处于“TIME_WAIT”状态,这显然是 TCP 在套接字关闭后(通常)60 秒所做的(为了捕获任何延迟的数据包)。我的印象是 Open MPI 没有关闭套接字(http://www.open-mpi.org/faq/?category=tcp#tcp-socket-closing),只是保持打开 N^2 个套接字,以便所有进程可以相互通信。显然 65536 远远超过 64^2(涉及 MPI 的此错误的最常见原因只是文件限制小于 N^2),其中大部分是处​​于最近关闭状态的套接字。

我们的 C++ 代码太大,无法放在这里,但我已经编写了其中一些代码的简化版本,以至少展示我们的实现并查看我们的技术是否存在任何问题。我们使用 MPI 时是否有什么东西会导致 OpenMPI 关闭并重新打开太多套接字?

namespace mpi = boost::mpi;
mpi::communicator world;

bool poll(ourDataType data, mpi::request & dataReq, ourDataType2 work, mpi::request workReq) {
if(dataReq.test()) {
processData(data); // do a bunch of work
dataReq = world.irecv(mpi::any_source, DATATAG, data);
return true;
}
if(workReq.test()) {
int target = assess(work);
world.send(target, DATATAG, dowork);
world.irecv(mpi::any_source, WORKTAG, data);
return true;
}
return false;
}

bool receiveFinish(mpi::request finishReq) {
if (finishReq.test()) {
world.send(0, RESULTS, results);
resetSelf();
finishReq = world.irecv(0, FINISH);
return true;
}
return false;
}

void run() {
ourDataType data;
mpi::request dataReq = world.irecv(mpi::any_source, DATATAG, data);
ourDataType2 work;
mpi::request workReq = world.irecv(mpi::any_source, WORKTAG, work);
mpi::request finishReq = world.irecv(0, FINISH); // the root process can call a halt

while(!receiveFinish(finishReq)) {
bool doWeContinue = poll(data, dataReq);
if(doWeContinue) {
continue;
}
// otherwise we do other work
results = otherwork();
world.send(0, RESULTS, results);
}
}

最佳答案

这可能不是 Open MPI 打开这么多套接字的真正原因,但您似乎在 poll() 函数的以下部分泄漏了请求:

if(workReq.test()) {
int target = assess(work);
world.send(target, DATATAG, dowork);
world.irecv(mpi::any_source, WORKTAG, data); // <-------
return true;
}

world.irecv() 返回的请求句柄永远不会保存,因此会丢失。如果在同一个 workReq 对象上定期调用,此分支将在每次请求完成后执行,因为测试一个已经完成的请求总是返回 true。因此,您将启动许多永远不会等待或测试的非阻塞接收。更不用说发送的消息了。

receiveFinish 中存在类似问题 - finishReq 正在按值传递,分配不会影响 run() 中的值。

旁注:这真的是您使用的代码吗?您在 run() 中调用的 poll() 函数似乎有两个参数,而此处显示的函数有四个参数,并且没有带默认值的参数。

关于sockets - 使用太多文件句柄打开 MPI 和 Boost MPI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24951210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com