2.6.3 AM Ping-Pong示例
虽然“Hello,World!”示例已经演示了每个GASNet应用程序开始结束所需的基础内容,但是除了屏障中隐含的内容外,该示例没有执行任何通信。因此,接下来我们展示了一个简单的使用GASNet的AM在节点对间执行“Ping-Pong”通信的例子。
该示例的第一部分如代码清单2-2所示,表示的是必需的AM处理程序。该代码在“Hello,World!”示例的框架中替换了第19行。此例中包括两个AM处理程序,其中每个AM处理程序都需要一个带单个参数的Short AM。“Ping”处理程序在响应AM请求时运行且只执行以下两个操作:打印带参的消息和发出AM Reply以调用参数相同的“Pong”处理程序。“Pong”处理程序主要负责打印不同的消息并递增计数器值。其中计数器通过使用GASNet工具的原子增量实现,以确保线程安全(计数器也是从main()中读取)。或者也可以使用pong_counter++,但需要HSL的保护。
本例的第二部分是main()函数逻辑,如代码清单2-3所示。在“Hello,World!”示例的框架中,该代码可以替换第32~34行。其中第3行的代码默认为2次迭代,但如果提供其他数字,它将从命令行中获取备选值。第6~7行的代码主要用于节点配对(0和1、2和3等),若节点数为奇数,那么将在最后一个节点上自身配对。示例的核心代码从第10行开始。每个节点对中编号较小的节点进行循环计数(count)迭代,并向另一个节点发送AM Request,然后阻塞直到对方的AM Reply增加了pong_count原子变量值。与此同时,节点对中编号较大的节点不在main()中执行相关工作,且在第20~21行调用屏障函数。节点对中的双方都必须运行AM才能保证示例正确执行。因此,偶数节点通过使用GASNET_BLOCKUNTIL等待“Pong”非常重要。如果代码改为如下的方式,则没有异步进程线程的GASNet实现将会产生死锁。
如果在没有附加命令行参数的3个节点上运行上述示例,输出结果如下所示。三个节点的输出结果按照时间顺序交织在一起打印到屏幕上。