基于此question,我认为创建新流程应该几乎与在Linux中创建新主题一样快。然而,很少测试显示出非常不同的结果。这是我的代码:
from multiprocessing import Process, Pool
from threading import Thread
times = 1000
def inc(a):
b = 1
return a + b
def processes():
for i in xrange(times):
p = Process(target=inc, args=(i, ))
p.start()
p.join()
def threads():
for i in xrange(times):
t = Thread(target=inc, args=(i, ))
t.start()
t.join()
测试:
>>> timeit processes()
1 loops, best of 3: 3.8 s per loop
>>> timeit threads()
10 loops, best of 3: 98.6 ms per loop
因此,创建过程几乎 40倍!为什么会这样?它是特定于Python还是这些库?还是我误解了上面的答案?
UPD 1。为了更清晰。据我所知,这段代码实际上并没有引入任何并发性。这里的目标是测试创建进程和线程所需的时间。要在Python中使用真正的并发,可以使用以下内容:
def pools():
pool = Pool(10)
pool.map(inc, xrange(times))
它的运行速度比线程版快得多。
UPD 2。我添加了os.fork()
的版本:
for i in xrange(times):
child_pid = os.fork()
if child_pid:
os.waitpid(child_pid, 0)
else:
exit(-1)
结果是:
$ time python test_fork.py
real 0m3.919s
user 0m0.040s
sys 0m0.208s
$ time python test_multiprocessing.py
real 0m1.088s
user 0m0.128s
sys 0m0.292s
$ time python test_threadings.py
real 0m0.134s
user 0m0.112s
sys 0m0.048s
答案 0 :(得分:5)
您所关联的问题是比较仅调用fork(2)
与pthread_create(3)
的费用,而您的代码执行的内容相当多,例如使用join()
等待进程/线程终止。
如果,如你所说......
这里的目标是测试创建进程和线程所需的时间。
...那么你不应该等他们完成。你应该使用更像这样的测试程序......
<强> fork.py 强>
import os
import time
def main():
for i in range(100):
pid = os.fork()
if pid:
#print 'created new process %d' % pid
continue
else:
time.sleep(1)
return
if __name__ == '__main__':
main()
<强> thread.py 强>
import thread
import time
def dummy():
time.sleep(1)
def main():
for i in range(100):
tid = thread.start_new_thread(dummy, ())
#print 'created new thread %d' % tid
if __name__ == '__main__':
main()
...给出以下结果......
$ time python fork.py
real 0m0.035s
user 0m0.008s
sys 0m0.024s
$ time python thread.py
real 0m0.032s
user 0m0.012s
sys 0m0.024s
...所以线程和进程的创建时间没有太大区别。
答案 1 :(得分:2)
是的,这是真的。开始一个新的流程(称为重量级流程)成本很高。
概述......
操作系统必须(在linux的情况下)fork第一个进程,设置新进程的记帐,设置新堆栈,执行上下文切换,复制任何更改的内存,并将所有内容拆除当新进程返回时。
线程只是分配一个新的堆栈和线程结构,上下文切换,并在工作完成时返回。
......这就是我们使用线程的原因。
答案 2 :(得分:1)
根据我的经验,创建一个线程(使用pthread_create
)和分支进程之间存在显着差异。
例如,我创建了一个类似于python测试的C测试,其代码如下:
pthread_t thread;
pthread_create(&thread, NULL, &test, NULL);
void *res;
pthread_join(thread, &res);
并像这样处理分叉代码:
pid_t pid = fork();
if (!pid) {
test(NULL);
exit(0);
}
int res;
waitpid(pid, &res, 0);
在我的系统上,分叉代码花了大约8倍的时间来执行。
然而,值得注意的是python的实现速度更慢 - 对我而言,它的速度大约是16倍。我怀疑这是因为除了创建新进程的常规开销之外,还有更多与新进程相关的python开销。