HPX 最小两节点示例设置?

HPX minimal two node example set-up?

HPX 入门 tutorial 假设您使用的是 PBS 或 slurm。这些在 HPC 社区中可能很常见,但作为开发人员,我更习惯这里有几台机器可以安装东西的场景。

像 slurm 这样的调度程序是需要利用多个物理机器还是只是为了方便管理集群,这并不是很明显。

我知道你可以在 运行 一个 HPX 应用程序(例如 this question)时使用 -l 标志模拟多个位置,我想要的是 运行 同一个应用程序在 2 个节点上并让它们相互通信。

告诉 HPX 所需的最低要求是什么:
这是您可以向其发送任务的具有此 IP 地址的另一台机器吗?

或者达到这个阶段的最低 slurm 配置是多少?

安装 slurm 很容易找到一个简单的 2 节点示例 so.Though this link to a podcast 可能会有帮助

我还假设 HPX 的包裹端口将仅在 TCP 上工作而无需安装任何额外的东西(例如 MPI)。这是正确的吗?


更新 我想我越来越近了,但我仍然缺少一些东西。 首先,我使用 hello_world 示例。会不会是2节点测试太简单了? 我希望在同一节点上获得与 运行ning 2 个位置类似的输出:

APP=$HPX/bin/hello_world
$APP --hpx:node 0 --hpx:threads 4 -l2 &
$APP --hpx:node 1 --hpx:threads 4 

示例输出:

hello world from OS-thread 2 on locality 0
hello world from OS-thread 0 on locality 0
hello world from OS-thread 1 on locality 1
hello world from OS-thread 3 on locality 1
hello world from OS-thread 2 on locality 1
hello world from OS-thread 1 on locality 0
hello world from OS-thread 0 on locality 1
hello world from OS-thread 3 on locality 0

但是当我尝试远程控制它时,两个进程都挂起:

$APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE0:7910 --hpx:threads 4 &
ssh $NODE1 $APP --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx.hpx=$NODE1:7910 --hpx:threads 4 

我在两台机器上都打开了7910端口。 $APP 的路径在两个节点上是相同的。 我不确定如何测试第二个进程是否正在与 agas 服务器通信。

如果我使用“--hpx:debug-agas-log=agas.log”和“--hpx:debug-hpx-log=hpx.log”,我得到:

>cat hpx.log 
(T00000000/----------------.----/----------------) P--------/----------------.---- 14:18.29.042 [0000000000000001]    [ERR] created exception: HPX(success)
(T00000000/----------------.----/----------------) P--------/----------------.---- 14:18.29.042 [0000000000000002]    [ERR] created exception: HPX(success)

在两台机器上。我不确定如何解释这个。

我尝试了一些其他选项,例如 --hpx:运行-agas-server (我认为这可能是通过使用 --hpx:agas=)

我也试过了

ssh $NODE1 $APP --hpx:nodes="$NODE0 $NODE1" &
$APP --hpx:nodes="$NODE0 $NODE1"

按照其他人的建议(现已删除?)没有运气回答。


更新 2

我认为这可能是防火墙问题,即使禁用了防火墙似乎也没有任何反应。我已经尝试 运行 跟踪系统调用,但没有任何明显的迹象:

echo "start server on agas master: node0=$NODE0"
strace -o node0.strace $APP \
 --hpx:localities=2 --hpx:agas=$NODE0:7910 --hpx:hpx=$NODE0:7910 --hpx:threads 4 &
cat agas.log hpx.log
echo "start worker on slave: node1=$NODE1"
ssh $NODE1 \
strace -o node1.strace $APP \
--hpx:worker --hpx:agas=$NODE0:7910 --hpx.hpx=$NODE1:7910 
echo "done"
exit 0

node0.strace 的尾部:

15:13:31 bind(7, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("172.29.0.160")}, 16) = 0 
15:13:31 listen(7, 128)                 = 0 
15:13:31 ioctl(7, FIONBIO, [1])         = 0 
15:13:31 accept(7, 0, NULL)             = -1 EAGAIN (Resource temporarily unavailable) 
...
15:13:32 mprotect(0x7f12b2bff000, 4096, PROT_NONE) = 0 
15:13:32 clone(child_stack=0x7f12b33feef0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f12b33ff9d0, tls=0x7f12b33ff700, child_tidptr=0x7f12b33ff9d0) = 22394 
15:13:32 futex(0x7ffe2c5df60c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0 
15:13:32 futex(0x7ffe2c5df5e0, FUTEX_WAKE_PRIVATE, 1) = 0 
15:13:32 futex(0x7ffe2c5df4b4, FUTEX_WAIT_PRIVATE, 1, NULL

node1.strace 的尾部:

6829 15:13:32 bind(7, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16) = 0 
16829 15:13:32 listen(7, 128)           = 0 
16829 15:13:32 ioctl(7, FIONBIO, [1])   = 0 
16829 15:13:32 accept(7, 0, NULL)       = -1 EAGAIN (Resource temporarily unavailable) 
16829 15:13:32 uname({sys="Linux", node="kmlwg-tddamstest3.grpitsrv.com", ...}) = 0 
16829 15:13:32 eventfd2(0, O_NONBLOCK|O_CLOEXEC) = 8 
16829 15:13:32 epoll_create1(EPOLL_CLOEXEC) = 9 
16829 15:13:32 timerfd_create(CLOCK_MONOTONIC, 0x80000 /* TFD_??? */) = 10 
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 8, {EPOLLIN|EPOLLERR|EPOLLET, {u32=124005464, u64=140359655238744}}) = 0 
16829 15:13:32 write(8, "[=17=][=17=][=17=][=17=][=17=][=17=][=17=]", 8) = 8 
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 10, {EPOLLIN|EPOLLERR, {u32=124005476, u64=140359655238756}}) = 0 
16829 15:13:32 futex(0x7fa8006f2d24, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7fa8006f2d20, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1 
16830 15:13:32  )    = 0 
16829 15:13:32 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP 
16830 15:13:32 futex(0x7fa8076432f0, FUTEX_WAKE_PRIVATE, 1) = 0 
16829 15:13:32  )   = 11 
16830 15:13:32 epoll_wait(9,  
16829 15:13:32 epoll_ctl(9, EPOLL_CTL_ADD, 11, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=124362176, u64=140359655595456}} 
16830 15:13:32  {{EPOLLIN, {u32=124005464, u64=140359655238744}}}, 128, -1) = 1 
16829 15:13:32  ) = 0 
16830 15:13:32 epoll_wait(9,  
16829 15:13:32 connect(11, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("172.29.0.160")}, 16 
16830 15:13:32  {{EPOLLHUP, {u32=124362176, u64=140359655595456}}}, 128, -1) = 1 
16830 15:13:32 epoll_wait(9,  

如果我在 master 上执行 strace -f,它的子进程循环会执行如下操作:

22050 15:12:46 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 12 
22050 15:12:46 epoll_ctl(5, EPOLL_CTL_ADD, 12, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=2395115776, u64=140516545171712}}) = 0 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46 connect(12, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46  )  = -1 ECONNREFUSED (Connection refused) 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46 futex(0x7fcc9cc20504, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1703, {1455808366, 471644000}, ffffffff 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46  )    = -1 ETIMEDOUT (Connection timed out) 
22050 15:12:46 futex(0x7fcc9cc204d8, FUTEX_WAKE_PRIVATE, 1) = 0 
22050 15:12:46 close(12)                = 0 
22050 15:12:46 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 12 
22050 15:12:46 epoll_ctl(5, EPOLL_CTL_ADD, 12, {EPOLLIN|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET, {u32=2395115776, u64=140516545171712}}) = 0 
22050 15:12:46 connect(12, {sa_family=AF_INET, sin_port=htons(7910), sin_addr=inet_addr("127.0.0.1")}, 16 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 
22050 15:12:46  )  = -1 ECONNREFUSED (Connection refused) 
22041 15:12:46 epoll_wait(5,  
22050 15:12:46 futex(0x7fcc9cc20504, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1705, {1455808366, 572608000}, ffffffff 
22041 15:12:46  {{EPOLLHUP, {u32=2395115776, u64=140516545171712}}}, 128, -1) = 1 

更新 3

精明的你可能已经注意到我在更新2中不小心写了 --hpx.hpx 而不是 --hpx:hpx。 你猜怎么着!改变它修复它。所以从技术上讲,第一个答案是正确的,我只是愚蠢。 我本以为命令行选项解析器会出错,但我想当你进行大规模并行时 运行time 你不能拥有一切:)。

感谢大家的帮助。

选项 1:当对网络层使用 TCP/IP 时(通常是默认值):

为了让 HPX 应用程序能够找到所有连接的节点,必须在批处理环境之外提供以下信息:

locality 0:
./yourapp --hpx:localities=2 --hpx:agas=node0:7910 --hpx:hpx=node0:7910 

locality 1:
./yourapp --hpx:agas=node0:7910 --hpx:hpx=node1:7910 --hpx:worker

其中 node0node1 是这些节点的主机名,7910 是要使用的(任意)TCP/IP 端口。

换句话说,

  • 在节点 0 上,您指定 HPX 将侦听此节点上的传入消息的端口 (--hpx:hpx=node0:7910) 以及活动全局地址 Space (AGAS) 引擎的主要实例将侦听的端口listen(这将用于其他节点建立初始连接(--hpx:agas=node0:7910)。您还指定总体 2 个地区将连接(--hpx:localities=2)。
  • 在节点 1(以及您要连接的所有其他节点)上,指定 HPX 将在此节点上侦听传入消息的端口 (--hpx:hpx=node1:7910) 以及可以访问主 AGAS 引擎的端口地点 0 (--hpx:agas=node0:7910)。您还可以指定本地是一个工作人员(而不是 'console'),这是通过 --hpx:worker 命令行选项完成的。

请注意,所有这些选项都有一个字母的快捷方式(--hpx:localities == -l--hpx:hpx == -x--hpx:agas == -a,并且 --hpx:worker == -w)

您还可以 运行 在同一个物理计算节点(或您的笔记本电脑)上使用多个位置。在这种情况下,指定一些东西就不那么乏味了,例如:

./yourapp -l2 -0 &
./yourapp -1

如果您想在这种情况下使用扩展命令行选项,请确保用于 -x 的端口在同一节点上 运行 的所有位置都是唯一的。

选项 2:使用 MPI 时(需要特殊的构建时间配置):

只需使用 mpi运行 来执行您的应用程序。它将从您的批处理环境中获取设置,或者它将使用命令行选项来 运行 事物。例如:

mpirun -N1 -np2 ./yourapp

这将 运行 当前计算节点上的应用程序的两个实例。

我无法对现有答案发表评论,因此我将重复@hkaiser 的答案中的一些信息:在 console/master 节点上或我们通常认为您应该使用的 rank0形式为

的命令
`bin/hello_world -l2 --hpx:agas=xx.xx.xx.AA:7910 --hpx:hpx=xx.xx.xx.AA:7910 `

并且在您应该使用的工作节点上

`bin/hello_world --hpx:agas=xx.xx.xx.AA:7910 --hpx:hpx=xx.xx.xx.BB:7910 --hpx:worker`

但重要的是,您使用的 IP 地址是节点的外部网络返回的 IP 地址,而不是内部网络(在多个 NIC/IP 地址的情况下)。为了确保我得到正确的地址,我通常 运行 命令

ip route get 8.8.8.8 | awk 'NR==1 {print $NF}'

在每个节点上,并在测试时使用该节点的输出。

请注意,仅当您 手动启动作业 而不是使用 mpi运行 或 s运行 启动作业时才需要此 IP 地址规范因为这些命令将在批处理系统分配的节点上生成作业,并且通信将由 HPX 内部正确处理。 使用批处理系统时,但仍然手动启动作业(例如,从交互式 shell 中,您会发现将选项 --hpx:ignore-batch-env 添加到命令行将有助于阻止 HPX 获取不需要的参数.

今天早上我尝试使用 HPX 存储库中的 git 提交 0c3174572ef5d2c,我的结果如下所示

主节点

bin/hello_world --hpx:agas=148.187.68.38:7910 --hpx:hpx=148.187.68.38:7910 -l2 --hpx:threads=4 hello world from OS-thread 3 on locality 1 hello world from OS-thread 6 on locality 1 hello world from OS-thread 2 on locality 1 hello world from OS-thread 7 on locality 1 hello world from OS-thread 5 on locality 1 hello world from OS-thread 0 on locality 1 hello world from OS-thread 4 on locality 1 hello world from OS-thread 1 on locality 1 hello world from OS-thread 0 on locality 0 hello world from OS-thread 2 on locality 0 hello world from OS-thread 1 on locality 0 hello world from OS-thread 3 on locality 0

工作节点

bin/hello_world --hpx:agas=148.187.68.38:7910 --hpx:hpx=148.187.68.36:7910 --hpx:worker --hpx:threads=8

请注意,可以像我在这里所做的那样在不同节点上使用不同数量的线程(但通常节点是同类的,因此您使用相同数量的线程)。

包裹运输

如果您编译时支持 MPI(例如)并且您希望确保使用 TCP parcelport,则添加

-Ihpx.parcel.tcp.enable=1 -Ihpx.parcel.mpi.enable=0

到您的命令行(在所有节点上)使 HPX 选择 TCP parcelport。