HPX最小双节点示例设置?

时间:2016-02-12 16:41:06

标签: c++ hpx

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

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

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

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

或者达到这个阶段的最低浆液配置是什么?

安装slurm很容易找到一个简单的2节点示例。尽管this link to a podcast可能有所帮助

我还假设HPX的parcel端口只能通过TCP工作而无需安装任何额外的东西(例如MPI)。这是对的吗?

更新 我想我越来越近但我仍然缺少一些东西。 首先我使用的是hello_world示例。难道它对于2节点测试来说太简单了吗? 我希望类似的输出在同一节点上运行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:run-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, "\1\0\0\0\0\0\0\0", 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。 你猜怎么着!改变它修复它。所以从技术上来说,第一个答案是正确的,我只是愚蠢。 我原本期望命令行选项解析器出错,但我想当你制作一个大规模并行运行时你不能拥有一切:)。

感谢大家的帮助。

2 个答案:

答案 0 :(得分:7)

选项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端口。

换句话说,

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

请注意,所有这些选项都有一个字母的快捷方式(--hpx:localities == -l--hpx:hpx == -x--hpx:agas == {{ 1}}和-a == --hpx:worker

您还可以在同一物理计算节点(或您的笔记本电脑)上运行多个位置。在这种情况下,指定内容有点不那么繁琐,例如:

-w

如果要在这种情况下使用扩展命令行选项,请确保用于./yourapp -l2 -0 & ./yourapp -1 的端口在同一节点上运行的所有位置都是唯一的。

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

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

-x

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

答案 1 :(得分:5)

我无法对现有的答案发表评论,所以我将从@hkaiser的答案中重复一些信息:在控制台/主节点或我们通常认为的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}'

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

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

今天早上我试用了HPX repo中的git commit 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

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

Parcelport

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

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

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