全局解释锁的制约
线程
以线程运行,收到全局解释锁的制约。
from threading import Thread
def loop():
while True:
pass
if __name__ == '__main__':
for i in range(3):
t = Thread(target=loop)
t.start()
while True:
pass
CPU 表现,虽然是多线程,但都集中到了一个单核上。
进程
以进程运行,不受全局解释锁的制约。
from multiprocessing import Process
def loop():
while True:
pass
if __name__ == '__main__':
for i in range(3):
t = Process(target=loop)
t.start()
while True:
pass
CPU 表现,唤醒全部的 CPU 核。
通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。
concurrent.futures
concurrent.futures 作为异步执行的高级别库,同时包括对线程和进程的处理,分别对应前面的 threading 和 multiprocessing。它的关键是以任务进行操作。
ThreadPoolExecutor
from concurrent import futures
import time
MAX_WORKERS = 20
POP20_CC = ('CN IN US ID BR PK NG BD RU JP '
'MX PH VN ET EG DE IR TR CD FR').split()
def download_one(cc):
while True:
pass
def download_many(cc_list):
workers = min(MAX_WORKERS, len(cc_list))
######
with futures.ThreadPoolExecutor(workers) as executor:
res = executor.map(download_one, sorted(cc_list))
return len(list(res))
def main(download_many):
t0 = time.time()
count = download_many(POP20_CC)
elapsed = time.time() - t0
msg = '\n{} flags downloaded in {:.2f}s'
print(msg.format(count, elapsed))
if __name__ == '__main__':
main(download_many)
ProcessPoolExecutor
from concurrent import futures
import time
MAX_WORKERS = 20
POP20_CC = ('CN IN US ID BR PK NG BD RU JP '
'MX PH VN ET EG DE IR TR CD FR').split()
def download_one(cc):
while True:
pass
def download_many(cc_list):
workers = min(MAX_WORKERS, len(cc_list))
######
with futures.ProcessPoolExecutor(workers) as executor:
res = executor.map(download_one, sorted(cc_list))
return len(list(res))
def main(download_many):
t0 = time.time()
count = download_many(POP20_CC)
elapsed = time.time() - t0
msg = '\n{} flags downloaded in {:.2f}s'
print(msg.format(count, elapsed))
if __name__ == '__main__':
main(download_many)