2.3.5 活动消息
AM接口作为GASNet核心API的主要内容,其原理是初始化节点上的调用向目标节点发送少量参数及可选负载,所有的这些都将传递给目标节点上的函数。将要运行的函数,如AM处理程序,通常由gasnet_handler_t类型的索引进行命名。其中这些索引与实际函数间的映射关系通过处理程序表传递给调用的gasnet_attach函数(有可能被其修改)的方式进行创建。
AM处理程序参数为32位的整型。参数的数目受限于具体实现,具体数字可以在运行时通过以下函数查询:
32位平台上函数返回的值至少等于8,而在64位平台上至少为16。目的是确保客户端可以每次向处理程序至少传递8个指针大小的值。
除了上述参数外,还有可选的负载项。我们把AM根据负载的处理方式分为三类:
- Short AM没有负载。Short AM处理程序的签名如下:
- Medium AM包含了在目标端实现并提供临时缓冲区的负载。对AM处理程序赋予此缓冲区地址及长度值,当处理程序完成时,将会清空其值并循环执行上述操作。此外,还可以在需要时修改负载项内容。Medium AM处理程序的签名如下:
- Long AM上包含由初始化节点提供并放置在目标节点地址上的负载。且其地址必须位于GASNet程序的段上。Long AM处理程序的签名如下:
在上述介绍的三个处理程序签名中,“…”表示最多有gasnet_AMMaxArgs()个附加参数变量。由于Medium和Long AM处理程序的签名相同,因此可以对它们使用同一处理程序。
负载大小受到程序实现相关限制的制约,可以通过以下函数进行查询:
GASNet规范中要求所有程序实现都必须支持至少512字节的负载,而在具有RMA支持的硬件平台中,该值会更大。重要的是要注意Long AM的Request与Reply间的区别。
可以使用以下函数中的任意一个发出AM请求,在目标节点上调用AM处理程序。
在上述函数中,“[N]”可以用从0到gasnet_AMMaxArgs()间的值替代。与之前的函数一样,“…”表示传给处理程序的32位参数值。对于Medium和Long请求而言,一旦负载内存可以安全地重用(也称为“本地完成”),函数就立即返回值。因为该实现不必对负载进行拷贝,因此可以暂时阻塞该函数调用,直至网络能够发送负载。当发生阻塞时,执行其他节点发送给调用节点的AM。LongAsync请求与无需等待本地完成的其他Long示例(那些等待分配资源依然处于阻塞状态)不同。在相关AM回复处理程序开始执行前,客户端不能够对负载进行修改,这也是判断本地完成的重要指示。虽然相关语义难以正确应用,但非常强大。
在AM处理程序执行时,相关代码在受限的、称为“处理程序背景”的环境中执行。我们将在后续的内容中讨论相关限制,本章重点关注GASNet中那些由伯克利AM定义的特征。这里的“至多回复一个”规则包含以下两点:(1)就AM的Request操作而言,处理程序中唯一允许的通信是对发起Request操作节点的可选回复;(2)对于AM的Reply操作,不允许在处理程序中发生通信。发送AM Reply操作的函数如下所示:
这里又一次出现了“…”,它表示32位处理程序的参数,且“[N]”表示在从0到gasnet_AMMaxArgs()参数的实例中的上述三种函数原型都是模板。
除了名称,发送AM Reply的调用函数与Request间的根本区别在于第一个参数的数据类型:gasnet_token_t。在上述的三种AM处理程序的函数原型中,该类型首次提及且并未给出详细解释。它是个不透明的类型,主要包括(至少)AM的源节点。由于难以构造这种类型的对象,因此调用AMReply函数的唯一方法是利用接受的标记符号做为Request处理程序的参数。如果必须知道AM的源节点(Request或Reply),这种情况可以使用如下函数查询:
上述函数只能从处理程序的上下文中进行,且标记符号参数的唯一有效值作为处理函数参数的接收值。