我是python多线程/多处理的新手,所以请耐心等待。 我想解决以下问题,在这方面我需要一些帮助/建议。 让我简要介绍一下:
我想启动一个python脚本,它可以在其中执行某些操作 顺序开始。
顺序部分结束后,我想开始一些工作 并行。
示例场景是:
以下是我的问题:
我很困惑---我应该使用多线程/多处理吗?哪一个更适合? 实际上这两者有什么区别?我读到了这些,但我无法得出结论。
什么是python GIL?我也在任何一个时间点读到某个地方只会执行一个线程。 我在这里需要一些解释。它让我觉得我无法使用线程。
关于如何系统地以更加pythonic的方式解决我的问题的任何建议。 我正在寻找一些口头的逐步解释和一些指针,以阅读每一步。 一旦概念清楚,我想自己编写代码。
提前致谢。
答案 0 :(得分:0)
1)从您在问题中列出的选项中,您可能应该在这种情况下使用multiprocessing
来利用多个CPU核心并并行计算。
2)从第1点开始:全局解释器锁(GIL)意味着任何时候只有一个线程可以实际执行代码。
在这里经常弹出的multithreading
的简单示例是提示用户输入,例如,数学问题的答案。在后台,他们希望计时器以一秒的间隔保持递增,以记录该人响应的时间。如果没有多线程,程序将在等待用户输入时阻塞,并且计数器不会递增。在这种情况下,您可以让计数器和输入提示在不同的线程上运行,以便它们看起来同时运行。实际上,两个线程共享相同的CPU资源,并且不断向前和向后传递一个对象(GIL)以授予它们对CPU的单独访问权限。如果你想要并行地正确处理事情,这是没有希望的。 (注意:实际上,您只需记录提示之前和之后的时间并计算差异而不是打扰线程。)
3)我使用multiprocessing
做了一个非常简单的例子。在这种情况下,我产生4个进程,计算随机选择范围的平方和。这些进程没有共享的GIL,因此不像multithreading
那样独立执行。在此示例中,您可以看到所有进程在稍微不同的时间开始和结束,但我们可以将进程的结果聚合到单个queue
对象中。在继续之前,父进程将等待所有4个子进程返回其计算。然后,您可以重复func_B
的代码(不包含在代码中)。
import multiprocessing as mp
import time
import random
import sys
def func_A(process_number, queue):
start = time.time()
print "Process {} has started at {}".format(process_number, start)
sys.stdout.flush()
my_calc = sum([x**2 for x in xrange(random.randint(1000000, 3000000))])
end = time.time()
print "Process {} has ended at {}".format(process_number, end)
sys.stdout.flush()
queue.put((process_number, my_calc))
def multiproc_master():
queue = mp.Queue()
processes = [mp.Process(target=func_A, args=(x, queue)) for x in xrange(4)]
for p in processes:
p.start()
# Unhash the below if you run on Linux (Windows and Linux treat multiprocessing
# differently as Windows lacks os.fork())
#for p in processes:
# p.join()
results = [queue.get() for p in processes]
return results
if __name__ == '__main__':
split_jobs = multiproc_master()
print split_jobs
答案 1 :(得分:0)
除了roganjosh的答案之外,我还会在A完成后包含一些信号来启动步骤B:
import multiprocessing as mp
import time
import random
import sys
def func_A(process_number, queue, proceed):
print "Process {} has started been created".format(process_number)
print "Process {} has ended step A".format(process_number)
sys.stdout.flush()
queue.put((process_number, "done"))
proceed.wait() #wait for the signal to do the second part
print "Process {} has ended step B".format(process_number)
sys.stdout.flush()
def multiproc_master():
queue = mp.Queue()
proceed = mp.Event()
processes = [mp.Process(target=func_A, args=(x, queue)) for x in range(4)]
for p in processes:
p.start()
#block = True waits until there is something available
results = [queue.get(block=True) for p in processes]
proceed.set() #set continue-flag
for p in processes: #wait for all to finish (also in windows)
p.join()
return results
if __name__ == '__main__':
split_jobs = multiproc_master()
print split_jobs