编写并行编程框架,我遗漏了什么?

16 投票
2 回答
914 浏览
提问于 2025-04-16 06:24

说明:根据一些评论,我需要澄清一下,这个框架是为了执行那些自然可以并行运行的程序(也就是所谓的“尴尬并行程序”)。它并不是,也永远不会是,解决需要进程之间通信或同步的任务的方案。

我一直在寻找一个简单的基于进程的并行编程环境,能够在集群的多个CPU上执行一个函数,主要的要求是能够执行不需要修改的Python代码。我找到的最接近的东西是Parallel Python,但它做了一些比较奇怪的事情,这可能导致代码在不正确的上下文中执行(比如没有导入合适的模块等)。

最后我厌倦了寻找,所以决定自己写一个。我想出来的其实很简单。问题是,我不确定我想出来的东西是否真的简单,可能是因为我没有考虑到很多事情。我的程序做了以下几件事:

  • 我有一个工作服务器,它把工作分配给集群中的节点。
  • 工作是通过传递一个字典分配给监听节点的服务器,这个字典看起来像这样:

    {
    'moduleName':'some_module', 
    'funcName':'someFunction', 
    'localVars': {'someVar':someVal,...}, 
    'globalVars':{'someOtherVar':someOtherVal,...}, 
    'modulePath':'/a/path/to/a/directory', 
    'customPathHasPriority':aBoolean, 
    'args':(arg1,arg2,...), 
    'kwargs':{'kw1':val1, 'kw2':val2,...}
    }
    
  • moduleNamefuncName是必须的,其他的都是可选的。

  • 一个节点服务器接收这个字典后会执行:

    sys.path.append(modulePath)
    globals()[moduleName]=__import__(moduleName, localVars, globalVars)
    returnVal = globals()[moduleName].__dict__[funcName](*args, **kwargs)
    
  • 得到返回值后,服务器会把它发送回工作服务器,工作服务器会把结果放入一个线程安全的队列中。

  • 当最后一个工作返回时,工作服务器会把输出写入文件并退出。

我相信还有一些小问题需要解决,但这个方法有没有明显的错误呢?乍一看,它似乎很稳健,只需要节点能够访问包含.py文件和依赖项的文件系统。使用__import__的好处是模块中的代码会自动运行,因此函数应该在正确的上下文中执行。

任何建议或批评都将非常感谢。

编辑:我应该提到,我已经让代码执行部分工作了,但服务器和工作服务器还没有写好。

2 个回答

5

我自己一直在尝试在不同的电脑上批量处理图片,最大的问题就是有些东西不能直接保存和通过网络传输。

比如说:pygame的表面(surfaces)不能直接保存。我需要把它们转换成字符串,先保存在StringIO对象里,然后再通过网络发送。

如果你要传输的数据(比如你的参数)是可以安全传输的,那你在网络数据方面就不会遇到太多问题。

还有一个问题:如果在执行任务的时候,有一台电脑突然“消失”了,你打算怎么办?在返回数据的时候呢?你有没有计划重新发送任务?

8

其实我写了一个可能能满足你需求的东西:jug。如果它不能解决你的问题,我保证会修复你发现的任何错误。

这个系统的架构稍微有点不同:所有的工作者都运行相同的代码,但它们实际上会生成一个类似的字典,并询问中央后台“这个任务有没有被执行过?”如果没有,它们就会执行这个任务(这里还有一个锁定机制)。如果你是在NFS系统上,后台可以简单地用文件系统来实现。

撰写回答