Vitajte na [www.pocitac.win] Pripojiť k domovskej stránke Obľúbené stránky
1. Multiprocessing (úlohy viazané na CPU):
- Kedy použiť: Ideálne pre úlohy, ktoré sú výpočtovo intenzívne (CPU viazané), ako je drvenie čísel, spracovanie obrazu alebo zložité výpočty. Tieto úlohy majú najviac úžitok z využívania viacerých jadier.
- Ako to funguje: Vytvára samostatné procesy, každý s vlastným pamäťovým priestorom. Tým sa zabráni obmedzeniam globálneho zámku tlmočníka (GIL), čo umožňuje skutočné paralelné vykonanie.
- Príklad:
`` `Python
importovať multiprientovanie
import
def process_item (položka):
"" Simuluje úlohu viazanú na procesor. ""
Time.sleep (1) # simulujte prácu
vrátenie položky * 2
def main ():
položky =zoznam (rozsah (10))
start_time =čas.time ()
s multiprocessing.pool (processes =multiprocessing.cpU_count ()) ako fondy:
Výsledky =Pool.map (Process_item, položky)
end_time =čas.time ()
tlač (f "Výsledky:{výsledky}")
tlač (F "Time Treat:{end_time - start_time:.2f} sekundy")
Ak __name__ =="__main__":
main ()
`` `
- Vysvetlenie:
- `multiprocessing.pool`:Vytvára skupinu pracovných procesov. `multiprocessing.cpu_count ()` Automaticky používa počet dostupných jadier.
- `Pool.map`:Aplikuje funkciu` Process_item` na každú položku v zozname `položky, distribúciu práce v procesoch pracovníkov. Automaticky spracováva rozdelenie práce a zhromažďovanie výsledkov.
- `Pool.Apply_async`:Nefamujúca alternatíva k` Pool.map`. Pre každú položku musíte zhromažďovať výsledky pomocou `result.get ()` pre každú položku.
- `Pool.imap` a` Pool.imap_unordered`:iterátory, ktoré vracajú výsledky, keď budú k dispozícii. `iMap_unordered` nezaručuje poradie výsledkov.
- `Pool.starmap`:Podobné ako` Pool.map`, ale umožňuje vám odovzdávať viac argumentov funkcii pracovníka pomocou n -tikov.
- Výhody:
- Prekoná obmedzenie GIL pre úlohy viazané na CPU.
- efektívne využíva viac jadier CPU.
- Nevýhody:
- Vyššie režijné náklady ako vlákno v dôsledku vytvárania samostatných procesov.
- Komunikácia medzi procesmi (odovzdávanie údajov) môže byť pomalšia.
- náročnejšie na pamäť, pretože každý proces má svoj vlastný pamäťový priestor.
- môže byť zložitejšia na správu zdieľaného stavu (potrebuje komunikačné mechanizmy medzi procesmi, ako sú fronty alebo zdieľaná pamäť).
2. Vlákno (úlohy viazané na I/O):
- Kedy použiť: Vhodný pre úlohy, ktoré trávia značné množstvo času čakaním na externé operácie (I/O viazané), ako sú požiadavky na sieť, diskové čítanie/zápisy alebo databázové dotazy.
- Ako to funguje: Vytvára viac vlákien v rámci jedného procesu. Vlákna zdieľajú rovnaký pamäťový priestor. GIL (Global Interpreter Lock) obmedzuje skutočný paralelizmus v cpythone, ale vlákna môžu stále zlepšiť výkon uvoľnením GIL, keď čakajú na I/O.
- Príklad:
`` `Python
importovaný závit
import
def fetch_url (URL):
"" Simuluje úlohu viazanú na I/O. ""
tlač (f "načítať {url}")
Time.sleep (2) # simulujte oneskorenie siete
Print (F "Hotovo načítavanie {url}")
Vráťte F "Obsah {url}"
def main ():
urls =["https://example.com/1", "https://example.com/2", "https://example.com/3"]
start_time =čas.time ()
vlákna =[]
Výsledky =[]
pre adresu URL v adresári URL:
vlákno =závitové
vlákna.prend (vlákno)
vlákno.start ()
Pre vlákno v vláknach:
Thread.Boin () # Počkajte, kým sa všetky vlákna dokončia
end_time =čas.time ()
tlač (f "Výsledky:{výsledky}")
tlač (F "Time Treat:{end_time - start_time:.2f} sekundy")
Ak __name__ =="__main__":
main ()
`` `
- Vysvetlenie:
- `Threading.Thread`:Vytvorí nové vlákno.
- `vlákno.start ()`:Spustí vykonanie vlákna.
- `vlákno.join ()`:čaká na dokončenie vlákna.
- Lambda funkcia: Používa sa na odovzdanie `url` ako argument na` fetch_url` v konštruktore `vlákna. Je nevyhnutné odovzdať `url` * podľa hodnoty *, aby sa predišlo rasovým podmienkam, kde by všetky vlákna mohli skončiť pomocou poslednej hodnoty` URL`.
- Výhody:
- nižšia režijná hodnota ako multiprocessing.
- zdieľa pamäťový priestor, čo uľahčuje zdieľanie údajov medzi vláknami (ale vyžaduje starostlivú synchronizáciu).
- Môže zlepšiť výkonnosť úloh v rámci I/O viazaných na I/O, napriek GIL.
- Nevýhody:
- GIL obmedzuje skutočný paralelizmus pre úlohy viazaných na CPU v Cpythone.
- Vyžaduje starostlivú synchronizáciu (zámky, semafory), aby sa zabránilo rasovým podmienkam a korupcii údajov pri prístupe k zdieľaným zdrojom.
3. Asyncio (súbežnosť s jedným vláknom):
- Kedy použiť: Vynikajúce na manipuláciu s veľkým počtom úloh viazaných na I/O súbežne v jednom vlákne. Poskytuje spôsob, ako napísať asynchrónny kód, ktorý dokáže prepínať medzi úlohami pri čakaní na dokončenie I/O operácií.
- Ako to funguje: Používa slučku udalostí na správu Coroutines (špeciálne funkcie deklarované pomocou „async def`). Coroutines dokáže pozastaviť svoje vykonanie pri čakaní na I/O a umožniť spustenie ďalších koroutín. `Asyncio` neposkytuje * skutočný paralelizmus (je to súbežnosť), ale môže byť vysoko efektívny pre operácie viazaných na I/O.
- Príklad:
`` `Python
importovať asyncio
import
async def fetch_url (URL):
"" "Simuluje úlohu viazanú na I/O (asynchrónne)." "
tlač (f "načítať {url}")
Očakávať asyncio.sleep (2) # simulovať sieťové oneskorenie (nezablokovanie)
Print (F "Hotovo načítavanie {url}")
Vráťte F "Obsah {url}"
async def main ():
urls =["https://example.com/1", "https://example.com/2", "https://example.com/3"]
start_time =čas.time ()
úlohy =[fetch_url (url) pre URL v URLS]
Výsledky =očakávať asyncio.gather (*úloh) # spúšťať úlohy súbežne
end_time =čas.time ()
tlač (f "Výsledky:{výsledky}")
tlač (F "Time Treat:{end_time - start_time:.2f} sekundy")
Ak __name__ =="__main__":
asyncio.run (main ())
`` `
- Vysvetlenie:
- `Async def`:Definuje asynchrónnu funkciu (coroutine).
- `Očakáva`:pozastavuje vykonanie Coroutine, kým sa očakávaná operácia nedokončí. Uvoľňuje kontrolu na slučku udalostí, čo umožňuje spustenie ostatných Coroutinov.
- `asyncio.sleep`:asynchrónna verzia„ Time.sleep`, ktorá nezablokuje slučku udalostí.
- `Asyncio.Gather`:prevádzkuje viacero Coroutine súbežne a vracia zoznam svojich výsledkov v poradí, v akom boli predložené. `*úlohy rozbaľujú zoznam úloh.
- `asyncio.run`:Spustí slučku Asyncio Event a prevádzkuje` main` coroutine.
- Výhody:
- Vysoko účinný pre úlohy viazaných na I/O, dokonca aj s jedným vláknom.
- Vyhýba sa režijnej budove vytvárania viacerých procesov alebo vlákien.
- Ľahšie spravovateľné súbežnosť ako vlákno (menšia potreba explicitných zámkov).
- Vynikajúce na budovanie vysoko škálovateľných sieťových aplikácií.
- Nevýhody:
- Vyžaduje použitie asynchrónnych knižníc a kódu, ktoré môžu byť zložitejšie učiť sa a ladiť ako synchrónny kód.
- Nie je vhodné pre úlohy viazané na CPU (neposkytuje skutočnú paralelizmus).
- spolieha sa na asynchrónne kompatibilné knižnice (napr. „AIOHTTP` namiesto` Request`).
4. Súbežné
- Kedy použiť: Poskytuje rozhranie na vysokej úrovni na vykonávanie úloh asynchrónne pomocou vlákien alebo procesov. Umožňuje prepínať medzi závitom a multiprocesom bez výraznej zmeny kódu.
- Ako to funguje: Používa „ThreadPooLExecutor“ na vlákno a „ProcessPooLExecutor“ na multiprocessing.
- Príklad:
`` `Python
import súbežné.
import
def process_item (položka):
"" Simuluje úlohu viazanú na procesor. ""
Time.sleep (1) # simulujte prácu
vrátenie položky * 2
def main ():
položky =zoznam (rozsah (10))
start_time =čas.time ()
s Concurrent.futures.ProcesspooLexecutor (max_workers =multiprocessing.cpu_count ()) ako exekútor:
# Odoslať každú položku exekútorovi
futures =[executor.submit (process_item, item) pre položku v položkách]
# Počkajte, kým sa dokončia všetky futures a získajú výsledky
Výsledky =[Future.Result () Pre budúcnosť v Concurrent.futures.as_completed (futures)]
end_time =čas.time ()
tlač (f "Výsledky:{výsledky}")
tlač (F "Time Treat:{end_time - start_time:.2f} sekundy")
Ak __name__ =="__main__":
importovať multiprientovanie
main ()
`` `
- Vysvetlenie:
- `Concurrent.futures.ProcesspooLExecutor`:Vytvára skupinu pracovných procesov. Môžete tiež použiť „concurrent.futures.THREADPOOLEXecutor“ pre vlákna.
- `Executor.submit`:predkladá calable (funkciu) exekútorovi pre asynchrónne vykonanie. Vráti objekt `Future` predstavujúci výsledok vykonávania.
- `Concurrent.futures.as_Completed`:iterátor, ktorý poskytuje„ budúce “objekty, keď ich dokončia, v žiadnom konkrétnom poradí.
- `Future.Result ()`:Získava výsledok asynchrónneho výpočtu. Bude blokovať, kým nebude k dispozícii výsledok.
- Výhody:
- Rozhranie na vysokej úrovni, zjednodušenie asynchrónneho programovania.
- Ľahko prepínajte medzi vláknami a procesmi zmenou typu exekútora.
- Poskytuje pohodlný spôsob riadenia asynchrónnych úloh a načítania ich výsledkov.
- Nevýhody:
- môže mať o niečo viac režijných nákladov, ako priamo používať multiprocessing “alebo` Threading` priamo.
Výber správneho prístupu:
| Prístup | Typ úlohy Obmedzenie GIL | Použitie pamäte | Zložitosť
| ------------------- | ------------------- | ---------------- | --------------- | ------------ |
| Multiprocessing | CPU viazaný Prekonať | Vysoká | Mierne |
| Vlákno I/O-viazané Áno | Nízka | Mierne |
| Asyncio | I/O-viazané Áno | Nízka | Vysoká |
| Súbežné. Futures | Obe | Závisí Líši sa Nízka |
Kľúčové úvahy:
* Typ úlohy (CPU-Bound vs. I/O-Bound): Toto je najdôležitejší faktor. Úlohy viazané na CPU majú úžitok z multiprocesívneho, zatiaľ čo úlohy viazané na I/O sú vhodnejšie pre vlákna alebo asyncio.
* gil (zámok globálneho tlmočníka): GIL v cpython obmedzuje skutočný paralelizmus pri vlákne. Ak potrebujete skutočný paralelizmus pre úlohy viazané na CPU, použite multiprocessing.
* Riadenie: Multiprocessing má vyššiu réžia ako vlákno a asyncio.
* Použitie pamäte: Multiprocessing používa viac pamäte, pretože každý proces má svoj vlastný pamäťový priestor.
* zložitosť: Asyncio sa môže učiť ako zložitejšie ako závitové alebo multiprocesné.
* Zdieľanie údajov: Zdieľanie údajov medzi procesmi (multiprocessing) vyžaduje interprocess komunikačné mechanizmy (fronty, zdieľanú pamäť), ktoré môžu zvýšiť zložitosť. Vlákna zdieľajú pamäťový priestor, ale vyžadujú starostlivú synchronizáciu, aby sa predišlo rasovým podmienkam.
* Podpora knižnice: Uistite sa, že knižnice, ktoré používate, sú kompatibilné s Asyncio, ak si vyberiete tento prístup. Mnoho knižníc teraz ponúka asynchrónne verzie (napr. „AIOHTTP` pre požiadavky HTTP).
osvedčené postupy:
* Profil váš kód: Pred implementáciou paralelizmu profil svoj kód na identifikáciu problémov. Neoptimalizujte predčasne.
* Merte výkon: Otestujte rôzne prístupy a zmerajte ich výkon, aby ste zistili, ktorý z nich je najlepšie pre váš konkrétny prípad použitia.
* uchovávajte úlohy nezávislé: Čím sú vaše úlohy nezávislejšie, tým ľahšie bude ich paralelizovať.
* Zvládnite výnimky: Správne zvládajte výnimky vo funkciách alebo Coroutine vášho pracovníka, aby ste im zabránili zlyhať celú aplikáciu.
* Použite fronty na komunikáciu: Ak potrebujete komunikovať medzi procesmi alebo vláknami, použite fronty, aby ste predišli rasovým podmienkam a zaistili bezpečnosť vlákna.
* Zvážte frontu správy: V prípade komplexných distribuovaných systémov zvážte použitie frontu správ (napr. RabbitMQ, Kafka) na spracovanie asynchrónnych úloh.
Starostlivo zvážením týchto faktorov si môžete zvoliť najúčinnejší prístup k vykonávaniu vašej slučky Python Run paralelne a výrazne zlepšiť výkon vašej aplikácie. Nezabudnite otestovať a zmerať výsledky, aby ste sa uistili, že váš zvolený prístup skutočne poskytuje výhodu výkonnosti.