Python est un langage qui s'exécute dans un interpréteur. Selon les recherches, Python possède un verrou global (GIL). Lors de l'utilisation du multi-threading (Thread), il ne peut pas tirer parti du multi-cœur. Cependant, l'utilisation du multi-processus (Multiprocess) peut tirer parti des avantages du multi-cœur pour réellement améliorer l'efficacité.
Expérience de comparaison
Selon les informations, si le processus multithread estintensif en CPUalors le multi-threading ne peut pas beaucoup améliorer l'efficacité ; au contraire, il peut même diminuer l'efficacité en raison de commutations fréquentes de threads, donc le multi-processus est recommandé ; s'il estintensif en E/Salors les processus multithread peuvent utiliser le temps d'inactivité pendant les attentes de blocage d'E/S pour exécuter d'autres threads, ce qui améliore l'efficacité. Par conséquent, nous comparons l'efficacité de différents scénarios au moyen d'expériences.
| Système d'exploitation | CPU | Mémoire | Disque dur |
|---|---|---|---|
| Windows 10 | Double cœur | 8GB | Disque dur mécanique |
(1) Importer les modules requis
import requests import time from threading import Thread from multiprocessing import Process
(2) Définir une fonction de calcul intensive en CPU
def count(x, y):
# 使程序完成50万计算
c = 0
while c < 500000:
c += 1
x += x
y += y
(3) Définir une fonction de lecture/écriture de fichier intensive en E/S
def write():
f = open("test.txt", "w")
for x in range(5000000):
f.write("testwrite\n")
f.close()
def read():
f = open("test.txt", "r")
lines = f.readlines()
f.close()
(4) Définir une fonction de requête réseau
_head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'}
url = "http://www.tieba.com"
def http_request():
try:
webPage = requests.get(url, headers=_head)
html = webPage.text
return {"context": html}
except Exception as e:
return {"error": e}
(5) Tester le temps nécessaire à l'exécution linéaire d'opérations intensives en E/S, d'opérations intensives en CPU et d'opérations intensives en requêtes réseau
# CPU密集操作
t = time.time()
for x in range(10):
count(1, 1)
print("Line cpu", time.time() - t)
# IO密集操作
t = time.time()
for x in range(10):
write()
read()
print("Line IO", time.time() - t)
# 网络请求密集型操作
t = time.time()
for x in range(10):
http_request()
print("Line Http Request", time.time() - t)
Sortie
Intensif en CPU : 95.6059999466, 91.57099986076355, 92.52800011634827, 99.96799993515015
Intensif en E/S : 24.25, 21.76699995994568, 21.769999980926514, 22.060999870300293
Intensif en requêtes réseau : 4.519999980926514, 8.563999891281128, 4.371000051498413, 4.522000074386597, 14.671000003814697
(6) Tester le temps nécessaire à l'exécution concurrente multithread d'opérations intensives en CPU
counts = []
t = time.time()
for x in range(10):
thread = Thread(target=count, args=(1,1))
counts.append(thread)
thread.start()
e = counts.__len__()
while True:
for th in counts:
if not th.is_alive():
e -= 1
if e <= 0:
break
print(time.time() - t)
Sortie : 25.69700002670288、24.02400016784668
(7) Tester le temps nécessaire à l'exécution concurrente multithread d'opérations intensives en E/S
def io():
write()
read()
t = time.time()
ios = []
t = time.time()
for x in range(10):
thread = Thread(target=count, args=(1,1))
ios.append(thread)
thread.start()
e = ios.__len__()
while True:
for th in ios:
if not th.is_alive():
e -= 1
if e <= 0:
break
print(time.time() - t)
Sortie : 99.9240000248 、101.26400017738342、102.32200002670288
(8) Tester le temps requis pour l'exécution concurrente multithread d'opérations intensives en réseau
t = time.time()
ios = []
t = time.time()
for x in range(10):
thread = Thread(target=http_request)
ios.append(thread)
thread.start()
e = ios.__len__()
while True:
for th in ios:
if not th.is_alive():
e -= 1
if e <= 0:
break
print("Thread Http Request", time.time() - t)
Sortie : 0.7419998645782471、0.3839998245239258、0.3900001049041748
(9) Tester le temps requis pour l'exécution concurrente multiprocessus d'opérations intensives en CPU
counts = []
t = time.time()
for x in range(10):
process = Process(target=count, args=(1,1))
counts.append(process)
process.start()
e = counts.__len__()
while True:
for th in counts:
if not th.is_alive():
e -= 1
if e <= 0:
break
print("Multiprocess cpu", time.time() - t)
Sortie : 54.342000007629395、53.437999963760376
(10) Tester l'exécution concurrente multiprocessus d'opérations intensives en E/S
t = time.time()
ios = []
t = time.time()
for x in range(10):
process = Process(target=io)
ios.append(process)
process.start()
e = ios.__len__()
while True:
for th in ios:
if not th.is_alive():
e -= 1
if e <= 0:
break
print("Multiprocess IO", time.time() - t)
Sortie : 12.509000062942505、13.059000015258789
(11) Tester l'exécution concurrente multiprocessus d'opérations intensives en requêtes HTTP
t = time.time()
httprs = []
t = time.time()
for x in range(10):
process = Process(target=http_request)
ios.append(process)
process.start()
e = httprs.__len__()
while True:
for th in httprs:
if not th.is_alive():
e -= 1
if e <= 0:
break
print("Multiprocess Http Request", time.time() - t)
Sortie : 0.5329999923706055、0.4760000705718994
Résultats expérimentaux
| Opérations intensives en CPU | Opérations intensives en E/S | Opérations intensives en requêtes réseau | |
|---|---|---|---|
| Opérations linéaires | 94.91824996469 | 22.46199995279 | 7.3296000004 |
| Opérations multithread | 101.1700000762 | 24.8605000973 | 0.5053332647 |
| Opérations multiprocessus | 53.8899999857 | 12.7840000391 | 0.5045000315 |
D'après les résultats ci-dessus, nous pouvons constater :
Le multithreading ne semble pas non plus présenter d'avantage significatif dans les opérations intensives en E/S (peut-être que si les tâches d'E/S étaient plus lourdes, l'avantage se manifesterait). Dans les opérations intensives en CPU, il est clairement moins performant que l'exécution linéaire monothread. Cependant, pour les opérations comme les requêtes réseau qui provoquent un blocage de thread en attente active, le multithreading présente un avantage très significatif.
Le multi-processus présente des avantages de performance dans les scénarios intensifs en CPU, intensifs en E/S et intensifs en requêtes réseau (opérations où des blocages de thread se produisent fréquemment). Cependant, pour les opérations similaires à celles intensives en requêtes réseau, il est presque identique au multithreading, mais consomme davantage de ressources telles que le CPU. Par conséquent, dans ce cas, nous pouvons choisir d'exécuter en multithreading.

Adresse d'origine : http://blog.atomicer.cn/2016/09/30/Python%E4%B8%AD%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%A4%9A%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%AF%B9%E6%AF%94/