当前位置: 首页 > 面试题库 >

如何将python dict与多处理同步

钱毅
2023-03-14
问题内容

我正在使用Python 2.6和用于多线程的多处理模块。现在,我希望有一个同步的字典(我真正需要的唯一原子操作是值上的+ =运算符)。

我应该用multiprocessing.sharedctypes.synchronized()调用包装字典吗?还是另一种方式?


问题答案:

介绍

似乎有很多主席建议,没有可行的例子。这里列出的答案都没有建议使用多处理,这令人失望和不安。作为python爱好者,我们应该支持我们的内置库,尽管并行处理和同步绝不是一件小事,但我相信可以通过适当的设计来使其琐碎。在现代多核体系结构中,这一点变得尤为重要,并且压力不足!就是说,我对多处理库不满意,因为它仍然处于起步阶段,存在很多陷阱,错误,并且倾向于函数式编程(我讨厌)。目前我还是比较喜欢Pyro由于在服务器运行时无法共享新创建的对象,因此多重处理的严重限制使得该模块比多重处理要领先(比其时间提前)。管理器对象的“注册”类方法仅在管理器(或其服务器)启动之前实际注册一个对象。ough不休,更多代码:

Server.py

from multiprocessing.managers import SyncManager


class MyManager(SyncManager):
    pass


syncdict = {}
def get_dict():
    return syncdict

if __name__ == "__main__":
    MyManager.register("syncdict", get_dict)
    manager = MyManager(("127.0.0.1", 5000), authkey="password")
    manager.start()
    raw_input("Press any key to kill server".center(50, "-"))
    manager.shutdown()

在上面的代码示例中,Server.py利用了多处理的SyncManager,它可以提供同步的共享对象。该代码将无法在解释器中运行,因为多处理库对于如何为每个已注册对象查找“可调用对象”非常敏感。运行Server.py将启动一个自定义的SyncManager,该共享文件夹共享syncdict字典以供多个进程使用,并且可以连接到同一台计算机上的客户端,或者如果在非环回的IP地址上运行,则可以连接到其他计算机。在这种情况下,服务器在端口5000上的回送(127.0.0.1)上运行。在操作syncdict时,使用authkey参数使用安全连接。按任意键时,管理器将关闭。

客户端

from multiprocessing.managers import SyncManager
import sys, time

class MyManager(SyncManager):
    pass

MyManager.register("syncdict")

if __name__ == "__main__":
    manager = MyManager(("127.0.0.1", 5000), authkey="password")
    manager.connect()
    syncdict = manager.syncdict()

    print "dict = %s" % (dir(syncdict))
    key = raw_input("Enter key to update: ")
    inc = float(raw_input("Enter increment: "))
    sleep = float(raw_input("Enter sleep time (sec): "))

    try:
         #if the key doesn't exist create it
         if not syncdict.has_key(key):
             syncdict.update([(key, 0)])
         #increment key value every sleep seconds
         #then print syncdict
         while True:
              syncdict.update([(key, syncdict.get(key) + inc)])
              time.sleep(sleep)
              print "%s" % (syncdict)
    except KeyboardInterrupt:
         print "Killed client"

客户端这次还必须创建一个自定义的SyncManager,注册“
syncdict”,而无需传入可调用来检索共享的dict。然后,它使用定制的SycnManager通过端口5000上的环回IP地址(127.0.0.1)和authkey建立到Server.py中启动的管理器的安全连接进行连接。它通过在管理器上调用已注册的可调用对象来检索共享的dict
syncdict。它提示用户以下内容:

  1. 同步操作的键
  2. 每个周期增加键访问的值的数量
  3. 每个周期的睡眠时间(以秒为单位)

然后,客户端检查密钥是否存在。如果不是,它将在syncdict上创建密钥。然后,客户端进入“无限”循环,在该循环中,客户端将按增量更新键的值,休眠指定的数量,并打印syncdict仅重复此过程,直到发生KeyboardInterrupt(Ctrl
+ C)。

烦人的问题

  1. 必须在启动管理器之前调用管理器的注册方法,否则即使在管理器上进行dir调用将显示它确实具有已注册的方法,也将获得异常。
  2. dict的所有操作都必须使用方法完成,而不是dict赋值(由于多处理共享定制对象的方式,syncdict [“ blast”] = 2会惨败)
  3. 使用SyncManager的dict方法将减轻烦人的问题2,但烦人的问题1会阻止SyncManager.dict()返回的代理被注册和共享。(仅在启动管理器之后才能调用SyncManager.dict(),并且只有在启动管理器之前才能注册,因此SyncManager.dict()仅在执行函数式编程并将代理作为参数传递给Processes时有用。 doc示例)
  4. 服务器和客户端都必须注册,即使直觉上看来,客户端在连接到管理器之后似乎也能够解决该问题(请将其添加到您的愿望清单多处理开发人员中)

闭幕

我希望您能像我一样享受这个相当彻底且耗时的答案。我直截了当遇到了很多麻烦,为什么在Pyro让它变得轻而易举的多处理模块上苦苦挣扎,现在由于这个答案,我的头上钉了钉子。我希望这对python社区在如何改进多处理模块方面很有用,因为我确实相信它有很大的希望,但在起步阶段还没有达到可能。尽管描述了烦人的问题,但我认为这仍然是一个可行的选择,并且非常简单。您还可以使用SyncManager.dict()并将其作为文档显示方式的参数传递给Processes,根据您的要求,这可能是一个甚至更简单的解决方案,这对我来说并不自然。



 类似资料:
  • 我有一个图像路径列表,我想在进程或线程之间划分,以便每个进程处理列表的某些部分。处理包括从磁盘加载图像,进行一些计算并返回结果。我正在使用Python 2.7 下面是我如何创建辅助进程 我所面临的问题是,当我在initializer函数中记录初始化时间时,我知道worker不是并行初始化的,而是每个worker都以5秒的间隔初始化,下面是供参考的日志 我尝试过使用将同时启动辅助线程 我知道Wind

  • 问题内容: 和之间有什么区别?将列表中的项目分配到4个进程后,它们是否运行相同的功能? 那么,假设两者都在异步和并行运行是错误的吗? 问题答案: 将作业映射到流程有四种选择。您必须考虑多个参数,并发性,阻塞和排序。并且仅在阻止方面有所不同。是非阻塞其中作为阻止 假设您有一个功能 输出示例: 将等待所有10个这些函数调用完成,因此我们可以连续查看所有打印件。 将异步执行它们,只有块时被调用,所以我们

  • 问题内容: 我使用安装了一个软件包,并运行其安装过程,在安装过程中,该软件包还安装了其他几个软件包,并将其添加到(假设)中,我假设使用 npm 。很好,但是现在我不同步了。 同步到当前状态的正确,非手动方法是什么? 编辑:将缺少的软件包显示为: 但这并没有添加它们。 问题答案: 奔跑,或只是。 锁定文件会在对依赖项进行任何更改时(即在您运行yarn命令时)完整更新。 从Yarn文档: 您的yarn

  • 我用的是Laravel和Stripe。我的应用程序中有5个不同的订阅计划。每个计划都有自己的一组选项,如 基本计划-最大活动-20-最大电子邮件-100 专业计划-最大活动-40-最大电子邮件-200 等 如何在数据库中表示这些选项? 我使用Laravel的收银台,它很好地处理订阅表,在那里它存储订阅名称,条纹计划id等。 但我希望稍后当用户准备创建一个活动时,检查他是否可以这样做,也就是说,他没

  • 问题内容: Java如何确定分配线程或进程的内核?有什么办法可以控制吗?防止两个大线程在同一内核上执行? 基本上,我要问的是有关Java中多线程如何工作或如何在Java中控制它的更多信息。 问题答案: 您不能为特定线程设置处理器关联。但是,如果将程序分为两个进程,则应该能够将这些进程分配给操作系统级别的特定处理器。 http://www.cyberciti.biz/tips/setting-pro

  • 我正在开发一个仅支持iPhone的iOS 8应用程序。我想只支持iPhone 4S的纵向模式设备。 我有一个图形设计,它采用全屏内容。我使用自动布局来处理视图,并使其适用于所有屏幕。但是,我使用一个小资产来管理从iPhone4S工作的设计。当我在iPhone6S/6看到它时,内容非常小,大量额外的空间被浪费了。 当设备分辨率变大时,我想增加字体大小、图像大小。这个应用程序中有很多屏幕。 例如,我在