Multithreading-in Python met Voorbeeld: Leer GIL in Python

⚡ Slimme samenvatting

Multithreading-in Python Het voert meerdere threads uit binnen één proces, waardoor ze geheugen delen en gelijktijdig werken. De threading-module creëert en beheert deze threads, terwijl de Global Interpreter Lock de werkelijke parallelle verwerking beperkt, waardoor de techniek het meest geschikt is voor taken die afhankelijk zijn van input/output.

  • 🔘 Thread versus proces: Een thread is een uitvoeringseenheid binnen een proces, en threads delen de procesgegevens terwijl ze afzonderlijk worden uitgevoerd.
  • ☑️ Twee modules: De verouderde _thread-module biedt functies op laag niveau, terwijl de module voor threading op een hoger niveau de moderne standaard is voor het bouwen van threads.
  • Threads aanmaken: Breid de Thread-klasse uit, overschrijf __init__ en run(), roep vervolgens start() aan om de thread te starten en join() om te wachten tot de uitvoering is voltooid.
  • 🧪 Vermijd raceomstandigheden: Een vergrendeling zorgt ervoor dat slechts één thread tegelijk een kritieke sectie kan betreden, waardoor deadlocks en beschadigde gedeelde gegevens worden voorkomen.
  • Begrijp de GIL: De Global Interpreter Lock maakt het mogelijk dat één thread tegelijkertijd kan draaien. Python bytecode per keer, dus CPU-intensieve taken vereisen multiprocessing.
  • 🤖 AI-werklasten: Multithreading versnelt input/output-gebonden AI-stappen zoals het laden van gegevens, terwijl NumPy en PyTorch geeft de GIL vrij voor parallelle berekeningen.

Multithreading-in Python

De Python Met een programmeertaal kun je gebruikmaken van multiprocessing of multithreading. In deze tutorial leer je hoe je multithreaded applicaties schrijft. Python.

Wat is een draad?

Een thread is een uitvoeringseenheid in parallel programmeren. Multithreading is een techniek waarmee een CPU meerdere taken van één proces tegelijk kan uitvoeren. Deze threads kunnen afzonderlijk worden uitgevoerd, terwijl ze de resources van het proces delen.

Wat is een proces?

Een proces is in principe het programma dat wordt uitgevoerd. Wanneer je een applicatie op je computer start (zoals een browser of tekstverwerker), maakt het besturingssysteem een ​​proces aan. proces.

Wat is multithreading? Python?

Multithreading-in Python Multithreading is een bekende techniek waarbij meerdere threads binnen een proces hun gegevensruimte delen met de hoofdthread. Dit maakt het delen van informatie en communicatie tussen threads eenvoudig en efficiënt. Threads zijn lichter dan processen. Meerdere threads kunnen afzonderlijk worden uitgevoerd, terwijl ze hun procesbronnen delen. Het doel van multithreading is om meerdere taken en functies tegelijkertijd uit te voeren.

Wat is multiprocessing?

multiprocessing stelt u in staat om meerdere ongerelateerde processen tegelijkertijd uit te voeren. Deze processen delen hun bronnen niet en communiceren via IPC.

Python Multithreading versus multiprocessing

Om processen en threads te begrijpen, kunt u het volgende scenario overwegen: Een .exe-bestand op uw computer is een programma. Wanneer u het opent, laadt het besturingssysteem het in het geheugen en voert de CPU het uit. De instantie van het programma die nu actief is, wordt het proces genoemd.

Elk proces heeft twee fundamentele componenten:

  • De Code
  • De data

Nu kan een proces een of meer zogenaamde subonderdelen bevatten threads. Dit hangt af van de architectuur van het besturingssysteem. Je kunt een thread zien als een gedeelte van een proces dat door het besturingssysteem afzonderlijk kan worden uitgevoerd.

Met andere woorden, het is een stroom instructies die onafhankelijk van elkaar door het besturingssysteem kunnen worden uitgevoerd. Threads binnen één proces delen de gegevens van dat proces en zijn ontworpen om samen te werken en zo parallelle verwerking mogelijk te maken.

Waarom multithreading gebruiken?

Met multithreading kunt u een applicatie opsplitsen in meerdere subtaken en deze taken tegelijkertijd uitvoeren. Als u multithreading op de juiste manier gebruikt, kunnen de snelheid, prestaties en rendering van uw applicatie worden verbeterd.

Python multithreading

Python Het biedt ondersteuning voor zowel multiprocessing als multithreading. In deze handleiding ligt de focus voornamelijk op de implementatie. meerdradig toepassingen met PythonEr zijn twee hoofdmodules die gebruikt kunnen worden om threads te beheren. Python:

  1. De draad module, en
  2. De threading module

Echter, in PythonEr bestaat ook zoiets als een globale interpretervergrendeling (GIL). Deze biedt niet veel prestatiewinst en kan zelfs nadelig zijn. verminderen de prestaties van sommige multithreaded applicaties. Je leert er alles over in de komende secties van deze tutorial.

De modules Draad en Draadsnijden

De twee modules waarover u in deze zelfstudie leert, zijn de draadmodule en draadmodule.

De threadmodule is echter al lang verouderd. Te beginnen met Python 3, is het als verouderd aangemerkt en is het alleen toegankelijk als _draad voor achterwaartse compatibiliteit.

Je moet het hogere niveau gebruiken threading module voor applicaties die u wilt implementeren. De threadmodule is hier alleen ter illustratie behandeld.

De draadmodule

De syntaxis voor het maken van een nieuwe thread met deze module is als volgt:

thread.start_new_thread(function_name, arguments)

Oké, nu heb je de basistheorie behandeld om te beginnen met coderen. Open dus uw IDLE of een kladblok en typ het volgende:

import time
import _thread

def thread_test(name, wait):
   i = 0
   while i <= 3:
      time.sleep(wait)
      print("Running %s\n" %name)
      i = i + 1

   print("%s has finished execution" %name)

if __name__ == "__main__":
    
    _thread.start_new_thread(thread_test, ("First Thread", 1))
    _thread.start_new_thread(thread_test, ("Second Thread", 2))
    _thread.start_new_thread(thread_test, ("Third Thread", 3))

Sla het bestand op en druk op F5 om het programma uit te voeren. Als alles correct is gedaan, is dit de uitvoer die u zou moeten zien:

De draadmodule

In de volgende hoofdstukken leer je meer over de wedstrijdomstandigheden en hoe je daarmee om moet gaan.

De draadmodule

CODE-UITLEG

  1. Deze instructies importeren de tijd- en threadmodule, die worden gebruikt om de uitvoering en vertraging van de taken te beheren. Python threads.
  2. Hier hebt u een functie gedefinieerd met de naam draad_test, die zal worden gebeld door de start_nieuwe_thread methode. De functie voert een while-lus vier keer uit en print de naam van de thread die de functie heeft aangeroepen. Zodra de iteratie is voltooid, print de functie een bericht dat de thread klaar is met uitvoeren.
  3. Dit is het hoofdgedeelte van je programma. Hier belt u eenvoudigweg de start_nieuwe_thread methode met de draad_test Geef de functie als argument mee. Hiermee wordt een nieuwe thread aangemaakt voor de functie die je als argument doorgeeft en wordt deze uitgevoerd. Merk op dat je dit (thread_test) kunt vervangen door elke andere functie die je als thread wilt uitvoeren.

De draadmodule

Deze module is de implementatie op hoog niveau van threading in Python Het is de de facto standaard voor het beheren van multithreaded applicaties. Het biedt een breed scala aan functies in vergelijking met de threadmodule.

Structuur van de draadsnijmodule

Structuur van de draadsnijmodule

Hier is een lijst met enkele nuttige functies die in deze module zijn gedefinieerd:

Functie Naam Beschrijving
actieveAantal() Retourneert het aantal van Draad objecten die nog leven.
huidigeDraad() Retourneert het huidige object van de klasse Thread.
opsommen () Geeft een overzicht van alle actieve Thread-objecten.
isDaemon() Retourneert true als de thread een daemon is.
is levend() Retourneert waar als de thread nog leeft.
Thread Class-methoden
begin() Start de activiteit van een thread. Het moet voor elke thread slechts één keer worden aangeroepen, omdat er een runtimefout ontstaat als het meerdere keren wordt aangeroepen.
rennen() Deze methode geeft de activiteit van een thread aan en kan worden overschreven door een klasse die de Thread-klasse uitbreidt.
meedoen () Het blokkeert de uitvoering van andere code totdat de thread waarop de methode join() werd aangeroepen, wordt beëindigd.

Achtergrondverhaal: de draadklasse

Voordat je begint met het programmeren van multithreaded programma's met behulp van de threading-module, is het essentieel om de Thread-klasse te begrijpen. De Thread-klasse is de primaire klasse die de template en de bewerkingen van een thread definieert. Python.

De meest gebruikelijke manier om een ​​multithreaded applicatie te creëren Python De bedoeling van de applicatie is om een ​​klasse te declareren die de Thread-klasse uitbreidt en de run()-methode ervan overschrijft.

Samenvattend betekent de Thread-klasse een codereeks die in een afzonderlijke codereeks wordt uitgevoerd draad van controle.

Wanneer u een multithreaded app schrijft, doet u het volgende:

  1. Definieer een klasse die de Thread-klasse uitbreidt.
  2. Overschrijf de __in het__ aannemer
  3. Overschrijf de rennen() methode

Zodra een draadobject is gemaakt, wordt het begin() Deze methode kan worden gebruikt om de uitvoering van deze activiteit te starten, en de meedoen () methode kan worden gebruikt om alle andere code te blokkeren totdat de huidige activiteit is voltooid.

Laten we nu proberen de threading-module te gebruiken om uw vorige voorbeeld te implementeren. Start uw applicatie opnieuw op. IDLE en typ het volgende in:

import time
import threading

class threadtester (threading.Thread):
    def __init__(self, id, name, i):
       threading.Thread.__init__(self)
       self.id = id
       self.name = name
       self.i = i
       
    def run(self):
       thread_test(self.name, self.i, 5)
       print ("%s has finished execution " %self.name)

def thread_test(name, wait, i):

    while i:
       time.sleep(wait)
       print ("Running %s \n" %name)
       i = i - 1

if __name__=="__main__":
    thread1 = threadtester(1, "First Thread", 1)
    thread2 = threadtester(2, "Second Thread", 2)
    thread3 = threadtester(3, "Third Thread", 3)

    thread1.start()
    thread2.start()
    thread3.start()

    thread1.join()
    thread2.join()
    thread3.join()

Dit zal de uitvoer zijn wanneer u de bovenstaande code uitvoert:

Achtergrondverhaal: de draadklasse

CODE-UITLEG

Achtergrondverhaal: de draadklasse

  1. Dit deel is hetzelfde als ons vorige voorbeeld. Hier importeer je de modules voor tijd en threads, die worden gebruikt om de uitvoering en vertragingen van de code te beheren. Python threads.
  2. In dit bit maak je een klasse met de naam threadtester, die de Draad klasse van de threading-module. Dit is een van de meest gebruikelijke manieren om threads te creëren in PythonJe moet echter alleen de constructor en de rennen() methode in uw app. Zoals je in het bovenstaande codevoorbeeld kunt zien, is de __in het__ methode (constructor) is overschreven. Op dezelfde manier heb je ook de rennen() methode. Het bevat de code die u in een thread wilt uitvoeren. In dit voorbeeld heb je de functie thread_test() aangeroepen.
  3. Dit is de thread_test() methode, die de waarde van als argument neemt. i Als argument wordt i bij elke iteratie met 1 verlaagd, en de rest van de code wordt herhaald totdat i 0 wordt. Bij elke iteratie wordt de naam van de momenteel actieve thread afgedrukt en wordt er gewacht op wait seconden (wat ook als argument wordt meegegeven).
  4. thread1 = threadtester(1, “Eerste Thread”, 1) Hier maken we een thread en geven we de drie parameters door die we hebben aangegeven in __init__. De eerste parameter is de ID van de thread, de tweede parameter is de naam van de thread en de derde parameter is de teller, die bepaalt hoe vaak de while-lus moet worden uitgevoerd.
  5. thread2.start() De start-methode wordt gebruikt om de uitvoering van een thread te starten. Intern roept de start()-functie de run()-methode van uw klasse aan.
  6. thread3.join() De methode join() blokkeert de uitvoering van andere code en wacht tot de thread waarop deze is aangeroepen, is voltooid.

Zoals u wellicht al weet, hebben threads binnen hetzelfde proces toegang tot het geheugen en de gegevens van dat proces. Als gevolg hiervan kunnen er fouten optreden als meer dan één thread tegelijkertijd probeert de gegevens te wijzigen of te benaderen.

In het volgende gedeelte ziet u de verschillende soorten complicaties die kunnen optreden wanneer threads toegang krijgen tot gegevens en de kritieke sectie zonder te controleren op bestaande toegangstransacties.

Deadlocks en raceomstandigheden

Voordat we dieper ingaan op deadlocks en raceomstandigheden, is het handig om een ​​paar basisdefinities met betrekking tot parallel programmeren te begrijpen:

  • Kritieke sectie: Het is een stukje code dat toegang krijgt tot gedeelde variabelen of deze wijzigt, en moet worden uitgevoerd als een atomaire transactie.
  • Contextwisseling: Het is het proces dat een CPU volgt om de status van een thread op te slaan voordat er van de ene taak naar de andere wordt overgeschakeld, zodat de thread later vanaf hetzelfde punt kan worden hervat.

impasses

impasses zijn de meest gevreesde problemen waar ontwikkelaars mee te maken krijgen bij het schrijven van gelijktijdige/multithreaded applicaties in PythonDe beste manier om deadlocks te begrijpen is door gebruik te maken van het klassieke voorbeeldprobleem uit de informatica, bekend als de deadlock. Dineren Philosofers Probleem.

De probleemstelling voor eetfilosofen luidt als volgt:

Vijf filosofen zitten aan een ronde tafel met vijf borden spaghetti (een soort pasta) en vijf vorken, zoals weergegeven in het diagram.

Dineren Philosofers Probleem

Dineren Philosofers Probleem

Een filosoof moet op elk willekeurig moment óf eten óf denken.

Bovendien moet een filosoof de twee vorken die naast hem liggen (d.w.z. de linker- en rechtervork) pakken voordat hij de spaghetti kan eten. Het probleem van deadlock doet zich voor wanneer alle vijf filosofen tegelijkertijd hun rechtervork oppakken.

Omdat elke filosofen één vork heeft, zullen ze allemaal wachten tot de anderen hun vork neerleggen. Als gevolg hiervan zal niemand van hen spaghetti kunnen eten.

Op dezelfde manier treedt er in een gelijktijdig systeem een ​​deadlock op wanneer verschillende threads of processen (philosophers) tegelijkertijd proberen de gedeelde systeembronnen (forks) te verwerven. Als gevolg hiervan krijgt geen van de processen de kans om uit te voeren, omdat ze wachten op een andere bron die door een ander proces wordt vastgehouden.

Race voorwaarden

Een raceconditie is een ongewenste toestand van een programma die optreedt wanneer een systeem twee of meer bewerkingen tegelijk uitvoert. Neem bijvoorbeeld deze eenvoudige for-lus:

i=0; # a global variable
for x in range(100):
    print(i)
    i+=1;

Als je creëert n Door het aantal threads dat deze code tegelijkertijd uitvoert, kunt u de waarde van i (die door de threads wordt gedeeld) niet bepalen wanneer het programma klaar is met uitvoeren. Dit komt doordat in een echte multithreading-omgeving threads elkaar kunnen overlappen, en de waarde van i die door een thread is opgehaald en gewijzigd, kan veranderen wanneer een andere thread er toegang toe krijgt.

Dit zijn de twee belangrijkste soorten problemen die kunnen optreden in een multithreaded of gedistribueerde omgeving. Python applicatie. In het volgende gedeelte leert u hoe u dit probleem kunt oplossen door threads te synchroniseren.

Syncroniserende draden

Om met race-omstandigheden, deadlocks en andere thread-gebaseerde problemen om te gaan, biedt de threading-module de volgende mogelijkheden: Slot object. Het idee is dat wanneer een thread toegang wil tot een specifieke resource, deze een lock voor die resource verkrijgt. Zodra een thread een bepaalde resource lockt, kan geen enkele andere thread er toegang toe krijgen totdat de lock wordt vrijgegeven. Als gevolg hiervan zullen de wijzigingen aan de resource atomisch zijn en worden racecondities afgewend.

Een slot is een synchronisatieprimitief op laag niveau dat wordt geïmplementeerd door de _draad module. Op elk willekeurig moment kan een vergrendeling zich in één van twee toestanden bevinden: opgesloten or ontgrendeld. Het ondersteunt twee methoden:

  1. verwerven(): Wanneer de vergrendelingsstatus wordt opgeheven, zal het aanroepen van de acquire()-methode de status wijzigen naar vergrendeld en terugkeren. Als de status echter vergrendeld is, wordt de aanroep van acquire() geblokkeerd totdat de release()-methode door een andere thread wordt aangeroepen.
  2. uitgave(): De release()-methode wordt gebruikt om de status op ontgrendeld te zetten, dat wil zeggen om een ​​vergrendeling op te heffen. Het kan door elke thread worden aangeroepen, niet noodzakelijkerwijs degene die het slot heeft verkregen.

Hier is een voorbeeld van het gebruik van vergrendelingen in uw apps. Start uw app op. IDLE en typ het volgende:

import threading
lock = threading.Lock()

def first_function():
    for i in range(5):
        lock.acquire()
        print ('lock acquired')
        print ('Executing the first funcion')
        lock.release()

def second_function():
    for i in range(5):
        lock.acquire()
        print ('lock acquired')
        print ('Executing the second funcion')
        lock.release()

if __name__=="__main__":
    thread_one = threading.Thread(target=first_function)
    thread_two = threading.Thread(target=second_function)

    thread_one.start()
    thread_two.start()

    thread_one.join()
    thread_two.join()

Druk nu op F5. Je zou een uitvoer als deze moeten zien:

Syncroniserende discussies

CODE-UITLEG

Syncroniserende discussies

  1. Hier maakt u eenvoudigweg een nieuw slot aan door de draadsnijden.Lock() fabrieksfunctie. Intern retourneert Lock() een instantie van de meest effectieve concrete Lock-klasse die door het platform wordt onderhouden.
  2. In de eerste instructie verkrijgt u het slot door de methode acquire() aan te roepen. Wanneer de vergrendeling is verleend, drukt u af “slot verworven” naar de console. Zodra alle code die u door de thread wilt laten uitvoeren, is uitgevoerd, geeft u de vergrendeling vrij door de methode release() aan te roepen.

De theorie is prima, maar hoe weet je zeker dat de vergrendeling echt werkte? Als je naar de uitvoer kijkt, zie je dat elke printopdracht precies één regel tegelijk afdrukt. Denk terug aan een eerder voorbeeld, waar de uitvoer van print willekeurig was omdat meerdere threads tegelijkertijd de print()-methode aanriepen. Hier wordt de printfunctie pas aangeroepen nadat de vergrendeling is verkregen. De uitvoer wordt dus één voor één en regel voor regel weergegeven.

Afgezien van sloten, Python Het ondersteunt ook een aantal andere mechanismen voor het synchroniseren van threads, zoals hieronder vermeld:

  1. RSloten
  2. Semaphores
  3. Voorwaarden
  4. Evenementen, en
  5. Barrières

Global Interpreter Lock (en hoe hiermee om te gaan)

Voordat we ingaan op de details van PythonLaten we, in het kader van GIL, een paar termen definiëren die nuttig zullen zijn voor het begrijpen van het volgende gedeelte:

  1. CPU-gebonden code: dit verwijst naar elk stuk code dat direct door de CPU wordt uitgevoerd.
  2. I/O-gebonden code: dit kan elke code zijn die via het besturingssysteem toegang krijgt tot het bestandssysteem.
  3. CPython: het is de referentie uitvoering of Python en kan worden omschreven als de tolk geschreven in C en Python (programmeertaal).

Waar zit GIL in? Python?

Wereldwijd tolkslot (GIL) in Python Een GIL (Global Interpreter Lock) is een procesvergrendeling of mutex die wordt gebruikt bij de interactie tussen processen. Het zorgt ervoor dat slechts één thread tegelijk toegang heeft tot een bepaalde bron en voorkomt dat objecten en bytecode tegelijkertijd worden gebruikt. Dit levert prestatieverbetering op voor single-threaded programma's. Python Het is heel eenvoudig en makkelijk te implementeren.

Een vergrendeling kan worden gebruikt om ervoor te zorgen dat slechts één thread op een bepaald moment toegang heeft tot een bepaalde bron.

Een van de kenmerken van Python Het verschil is dat het een globale vergrendeling toepast op elk interpreterproces, wat betekent dat elk proces de interpreter als zodanig behandelt. Python de tolk zelf als hulpmiddel.

Stel bijvoorbeeld dat u het volgende hebt geschreven: Python Een programma dat twee threads gebruikt om zowel CPU- als I/O-bewerkingen uit te voeren. Wanneer je dit programma uitvoert, gebeurt het volgende:

  1. De Python De interpreter creëert een nieuw proces en start de threads.
  2. Wanneer thread-1 begint te lopen, zal het eerst de GIL verkrijgen en vergrendelen.
  3. Als thread-2 nu wil uitvoeren, zal het moeten wachten tot de GIL wordt vrijgegeven, zelfs als er een andere processor vrij is.
  4. Stel nu dat thread-1 wacht op een I/O-bewerking. Op dat moment zal het de GIL vrijgeven en thread-2 zal deze verkrijgen.
  5. Als thread-1 na het voltooien van de I/O-bewerkingen nu wil worden uitgevoerd, zal het opnieuw moeten wachten tot de GIL door thread-2 wordt vrijgegeven.

Hierdoor heeft slechts één thread tegelijk toegang tot de interpreter, wat betekent dat er slechts één thread tegelijk actief zal zijn. Python code op een bepaald moment.

Dit is prima op een processor met één kern, omdat deze gebruikmaakt van time slicing (zie het eerste deel van deze handleiding) om de threads af te handelen. Bij processoren met meerdere kernen heeft een CPU-intensieve functie die op meerdere threads draait echter een aanzienlijke impact op de efficiëntie van het programma, omdat niet alle beschikbare kernen tegelijkertijd worden gebruikt.

Waarom was GIL nodig?

de CPython De garbage collector gebruikt een efficiënte geheugenbeheertechniek die bekend staat als referentietelling. Zo werkt het: Elk object in Python Een object heeft een referentieteller, die wordt verhoogd wanneer het een nieuwe variabelenaam krijgt toegewezen of wordt toegevoegd aan een container (zoals tuples, lijsten, enz.). De referentieteller wordt eveneens verlaagd wanneer de referentie buiten het bereik valt of wanneer de `del`-instructie wordt aangeroepen. Wanneer de referentieteller van een object 0 bereikt, wordt het object door de garbage collector verwijderd en het toegewezen geheugen vrijgegeven.

Het probleem is echter dat de referentieteller, net als elke andere globale variabele, gevoelig is voor racecondities. Om dit probleem op te lossen, hebben de ontwikkelaars van Python We hebben ervoor gekozen om de globale interpretervergrendeling te gebruiken. De andere optie was om aan elk object een vergrendeling toe te voegen, wat zou hebben geleid tot deadlocks en een verhoogde overhead door de acquire() en release() aanroepen.

Daarom vormt GIL een aanzienlijke beperking voor multithreading. Python Programma's die zware, CPU-intensieve bewerkingen uitvoeren (waardoor ze in feite single-threaded zijn). Als u meerdere CPU-cores in uw applicatie wilt gebruiken, gebruik dan de multiverwerking module in plaats daarvan.

Veelgestelde vragen

Gebruik threading voor I/O-intensieve taken zoals netwerkoproepen, bestandstoegang of databasequery's, waarbij threads wachten op externe resources. Gebruik multiprocessing voor CPU-intensieve taken zoals zware berekeningen, omdat dit op meerdere cores draait en de GIL omzeilt.

Niet standaard. PEP 703 introduceerde een optionele, threadvrije build. Python 3.13 die de GIL uitschakelt, en Python Versie 3.14 zet dit voort. Standaard builds bevatten nog steeds de GIL, waardoor de meeste programma's gewoon blijven werken zoals voorheen.

Een daemon-thread draait op de achtergrond en blokkeert het programma niet. Wanneer alleen daemon-threads overblijven, Python Sluit ze af en stopt. Stel er een in met thread.daemon = True voordat je start() aanroept.

De Thread-klasse retourneert het resultaat van run() niet rechtstreeks. Sla de waarde op in het thread-object of een gedeelde wachtrij, of gebruik concurrent.futures.ThreadPoolExecutor, waarvan de submit()-methode een Future retourneert die je vervolgens met result() kunt uitlezen.

ThreadPoolExecutor is een geavanceerde helper die een pool van workerthreads voor je beheert. Je dient taken in met submit() of map(), en de helper zorgt voor het aanmaken, hergebruiken en opruimen van threads, waarbij Future-objecten worden geretourneerd die elk resultaat bevatten.

Je kunt honderden of duizenden threads aanmaken, maar de GIL laat er maar één tegelijk toe. Python bytecode op elk willekeurig moment. Ze overlappen elkaar nog steeds tijdens I/O-wachttijden, dus veel gelijktijdige threads helpen I/O-intensieve programma's veel meer dan CPU-intensieve programma's.

Ja, vooral voor I/O-intensieve stappen zoals het laden van data, het aanroepen van API's of het lezen van bestanden. Intensieve training is CPU-intensief, dus daarvoor zijn bibliotheken zoals NumPy en Py geschikter.Torch geeft de GIL vrij in C-code of vertrouwt op multiprocessing voor echte parallelle verwerking.

Ja. GitHub Copilot vult automatisch veelvoorkomende patronen aan, zoals Thread-subklassen, Lock-gebruik en ThreadPoolExecutor-configuraties, op basis van een opmerking of functienaam. Controleer de gegenereerde code altijd op raceomstandigheden en correcte afhandeling van locks voordat u erop vertrouwt.

Vat dit bericht samen met: