令人困惑的并行Python问题 - TRANSPORT_SOCKET_TIMEOUT

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

下面的代码在我这儿似乎不太好使。它需要在你网络上的另一台电脑上启动一个ppserver,比如用下面的命令:

ppserver.py -r -a -w 4

一旦这个服务器启动后,我在我的电脑上运行这段代码:

import pp
import time
job_server = pp.Server(ppservers = ("*",))
job_server.set_ncpus(0)
def addOneBillion(x):
    r = x
    for i in xrange(10**9):
        r+=1
    f = open('/home/tomb/statusfile.txt', 'a')
    f.write('finished at '+time.asctime()+' for job with input '+str(x)+'\n')
    return r

jobs = []
jobs.append(job_server.submit(addOneBillion, (1,), (), ("time",)))
jobs.append(job_server.submit(addOneBillion, (2,), (), ("time",)))
jobs.append(job_server.submit(addOneBillion, (3,), (), ("time",)))

for job in jobs:
    print job()
print 'done'

奇怪的是:

我在看/home/tomb/statusfile.txt时,发现这个文件被写入了好几次,就像这个函数被运行了好几次一样。我观察过这个现象,持续了一个多小时,结果从来没有看到过job()返回。

更奇怪的是:

如果我把testfunc定义中的迭代次数改成10**8,函数只会运行一次,并且按预期返回结果!

这看起来像是某种竞争条件?只用本地的核心就没问题。这是使用pp版本1.6.0和1.5.7的情况。

更新:大约775,000,000时,我得到了不一致的结果:两个任务重复了一次,其中一个第一次就完成了。

一周后的更新:我写了自己的并行处理模块来解决这个问题,以后会避免使用Parallel Python,除非有人搞清楚这个问题 - 我会找时间再深入研究一下(实际上是查看源代码)。

几个月后的更新:对Parallel Python没有什么怨恨。我计划一有时间就把我的应用迁移回去。标题也改了,以反映解决方案。

2 个回答

1

这个库可能允许重复任务,因为有些节点处理得比较慢,导致还有很多任务没有完成。通过重复这些任务,可以绕过那些慢的节点,你只需要接受第一个完成的结果。为了避免这个问题,你可以给每个任务加一个独特的ID,只接受每个任务的第一个返回结果。

2

这是来自Parallel Python论坛的Bagira的回答:

每个任务的计算大概需要多长时间?你可以看看这个变量 TRANSPORT_SOCKET_TIMEOUT,它在 /usr/local/lib/python2.6/dist-packages/pptransport.py 这个文件里。

可能你的任务花费的时间比上面这个变量设置的时间要长。你可以把这个值调大一点,然后再试试。

结果发现,这正是我遇到的问题。在我的应用中,我使用PP作为批处理任务调度器,这些任务可能需要几分钟,所以我需要调整这个设置。(默认值是30秒)

撰写回答