全域性直譯器鎖

由於 Global Interpreter Lock, Python 多執行緒效能通常會受到影響。簡而言之,即使你可以在 Python 程式中擁有多個執行緒,但無論 CPU 數量多少,任何時候只能有一個位元組碼指令並行執行。

因此,在外部事件(如網路訪問)阻止操作的情況下,多執行緒可能非常有效:

import threading
import time

def process():
    time.sleep(2)

start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))

start = time.time()
threads = [threading.Thread(target=process) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.00s
# Out: Four runs took 2.00s

請注意,即使每個 process 執行 2 秒鐘,這四個程序一起能夠有效地並行執行,總共需要 2 秒。

但是,在 Python 程式碼中進行密集計算(例如大量計算)的情況下,多執行緒不會帶來太多改進,甚至可能比並行執行更慢:

import threading
import time

def somefunc(i):
    return i * i

def otherfunc(m, i):
    return m + i

def process():
    for j in range(100):
        result = 0
        for i in range(100000):
            result = otherfunc(result, somefunc(i))

start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))

start = time.time()
threads = [threading.Thread(target=process) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.05s
# Out: Four runs took 14.42s

在後一種情況下,多處理可以是有效的,因為多個程序當然可以同時執行多個指令:

import multiprocessing
import time

def somefunc(i):
    return i * i

def otherfunc(m, i):
    return m + i

def process():
    for j in range(100):
        result = 0
        for i in range(100000):
            result = otherfunc(result, somefunc(i))

start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))

start = time.time()
processes = [multiprocessing.Process(target=process) for _ in range(4)]
for p in processes:
    p.start()
for p in processes:
    p.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.07s
# Out: Four runs took 2.30s