📌  相关文章
📜  自然语言处理 |使用 Execnet 进行分布式标记 - 第 2 部分

📅  最后修改于: 2022-05-13 01:54:50.390000             🧑  作者: Mango

自然语言处理 |使用 Execnet 进行分布式标记 - 第 2 部分

网关的remote_exec()方法采用单个参数,该参数可以是以下三种类型之一:

  • 字符串要远程执行的代码
  • 将被序列化并远程执行的纯函数的名称
  • 将远程执行其源的纯模块的名称

代码:使用具有三个选项的 remote_tag.py 模块

import pickle
  
if __name__ == '__channelexec__':
    tagger = pickle.loads(channel.receive())
for sentence in channel:
    channel.send(tagger.tag(sentence))

什么是纯模块?

  • 纯模块是一个自包含的模块:它只能访问它执行时可用的Python模块,并且无法访问最初创建网关时存在的任何变量或状态。
  • 同样,纯函数是一个自包含的函数,没有外部依赖。
  • 要检测模块正在由 execnet 执行,请检查__name__变量。如果它等于'__channelexec__' ,那么它被用来创建一个远程通道。
  • 这类似于 if __name__ == '__main__'检查模块是否正在
    命令行。
  • 首先要做的是调用 channel.receive() 来获取序列化的标记器,它是使用pickle.loads()加载的
  • 请注意,通道不会在任何地方导入——这是因为它包含在模块的全局命名空间中。 execnet 远程执行的任何模块都可以访问通道变量,以便与通道创建者进行通信。
  • 在有了标注器之后,迭代地 tag() 每个标记化的句子,即从通道接收。
  • 这允许用户标记发送者想要发送的尽可能多的句子,因为在通道关闭之前迭代不会停止。
  • 因此,创建了一个用于词性标记的计算节点,将其 100% 的资源用于标记它收到的任何句子。只要通道保持打开状态,节点就可以进行处理。

Execnet 可以做的更多,例如打开多个通道以增加并行处理,以及通过 SSH 向远程主机打开网关以进行分布式处理。

创建多个频道
创建多个通道,每个网关一个,以使处理更加并行。每个网关创建一个新的子进程(或远程解释器,如果使用 SSH 网关),每个网关使用一个通道进行通信。一旦创建了两个通道,就可以使用 MultiChannel 类将它们组合起来,它允许用户遍历通道并创建一个接收队列来接收来自每个通道的消息。
创建每个通道并发送标记器后,通道循环以向每个通道发送偶数个句子进行标记。然后,从队列中收集所有响应。对queue.get()的调用将返回 (channel, message) 的 2 元组,以防需要知道消息来自哪个通道。一旦收集了所有标记的句子,就可以轻松退出网关。

代码 :

import itertools
  
gw1 = execnet.makegateway()
gw2 = execnet.makegateway()
  
ch1 = gw1.remote_exec(remote_tag)
ch1.send(pickled_tagger)
ch2 = gw2.remote_exec(remote_tag)
ch2.send(pickled_tagger)
  
mch = execnet.MultiChannel([ch1, ch2])
queue = mch.make_receive_queue()
channels = itertools.cycle(mch)
  
for sentence in treebank.sents()[:4]:
    channel = next(channels)
    channel.send(sentence)
tagged_sentences = []
  
for i in range(4):
    channel, tagged_sentence = queue.get()
    tagged_sentences.append(tagged_sentence)
      
print ("Length : ", len(tagged_sentences))
  
gw1.exit()
gw2.exit()

输出 :

Length : 4

在示例代码中,只发送了四句话,但在现实生活中,一个需要发送数千个。一台计算机可以非常快速地标记四个句子,但是当需要标记数千或数十万个句子时,将句子发送到多台计算机比等待一台计算机完成所有操作要快得多。