令人困惑的并行Python问题 - TRANSPORT_SOCKET_TIMEOUT
下面的代码在我这儿似乎不太好使。它需要在你网络上的另一台电脑上启动一个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 个回答
这个库可能允许重复任务,因为有些节点处理得比较慢,导致还有很多任务没有完成。通过重复这些任务,可以绕过那些慢的节点,你只需要接受第一个完成的结果。为了避免这个问题,你可以给每个任务加一个独特的ID,只接受每个任务的第一个返回结果。
这是来自Parallel Python论坛的Bagira的回答:
每个任务的计算大概需要多长时间?你可以看看这个变量
TRANSPORT_SOCKET_TIMEOUT
,它在 /usr/local/lib/python2.6/dist-packages/pptransport.py 这个文件里。可能你的任务花费的时间比上面这个变量设置的时间要长。你可以把这个值调大一点,然后再试试。
结果发现,这正是我遇到的问题。在我的应用中,我使用PP作为批处理任务调度器,这些任务可能需要几分钟,所以我需要调整这个设置。(默认值是30秒)