美好的一天!
我正在尝试学习python中的多线程功能,并编写了以下代码:
import time, argparse, threading, sys, subprocess, os
def item_fun(items, indices, lock):
for index in indices:
items[index] = items[index]*items[index]*items[index]
def map(items, cores):
count = len(items)
cpi = count/cores
threads = []
lock = threading.Lock()
for core in range(cores):
thread = threading.Thread(target=item_fun, args=(items, range(core*cpi, core*cpi + cpi), lock))
threads.append(thread)
thread.start()
item_fun(items, range((core+1)*cpi, count), lock)
for thread in threads:
thread.join()
parser = argparse.ArgumentParser(description='cube', usage='%(prog)s [options] -n')
parser.add_argument('-n', action='store', help='number', dest='n', default='1000000', metavar = '')
parser.add_argument('-mp', action='store_true', help='multi thread', dest='mp', default='True')
args = parser.parse_args()
items = range(NUMBER_OF_ITEMS)
# print 'items before:'
# print items
mp = args.mp
if mp is True:
NUMBER_OF_PROCESSORS = int(os.getenv("NUMBER_OF_PROCESSORS"))
NUMBER_OF_ITEMS = int(args.n)
start = time.time()
map(items, NUMBER_OF_PROCESSORS)
end = time.time()
else:
NUMBER_OF_ITEMS = int(args.n)
start = time.time()
item_fun(items, range(NUMBER_OF_ITEMS), None)
end = time.time()
#print 'items after:'
#print items
print 'time elapsed: ', (end - start)
当我使用mp参数时,它工作得更慢,在我的机器上有4个cpus,计算结果需要大约0.5秒,而如果我使用单个线程需要大约0.3秒。
我做错了吗?
我知道有Pool.map()和e.t.c,但是它产生子进程而不是线程,据我所知它的工作速度更快,但我想编写自己的线程池。
答案 0 :(得分:5)
由于名为“GIL”的实现细节,Python没有真正的多线程。实际上一次只运行一个线程,Python在线程之间切换。 (Python的第三方实现,例如Jython,可以actually run parallel threads。)
至于为什么实际你的程序在多线程版本中的速度较慢,但是在编写Python时,需要注意GIL,因此不相信CPU绑定负载更多通过向程序添加线程来有效地处理。
其他需要注意的事项是,例如multiprocessing和numpy用于解决CPU绑定负载,PyEv(最小)和Tornado(巨大的厨房水槽)解决I / O绑定负载。
答案 1 :(得分:4)
如果您的线程是IO绑定的,那么您只会看到Python中的线程吞吐量增加。如果你正在做的是CPU绑定,那么你将看不到任何吞吐量增加。
打开Python中的线程支持(通过启动另一个线程)似乎也会使某些事情变得更慢,因此您可能会发现整体性能仍然受到影响。
这当然是cpython,其他Python实现有不同的行为。