Mitme lõime sisse lülitamine Python näitega: õppige GIL sisse Python

⚡ Nutikas kokkuvõte

Mitme lõime sisse lülitamine Python käitab ühe protsessi sees mitut lõime, nii et nad jagavad mälu ja töötavad samaaegselt. Lõimede moodul loob ja haldab neid lõime, samas kui globaalne interpretaatori lukk piirab tegelikku paralleelsust, muutes selle tehnika parimaks sisend-/väljundiga seotud ülesannete jaoks.

  • 🔘 Lõim vs protsess: Lõim on protsessi sees olev täitmisüksus ja lõimed jagavad protsessiandmeid individuaalselt töötades.
  • ☑️ Kaks moodulit: Vananenud _thread moodul pakub madala taseme kõnesid, samas kui kõrgema taseme lõimemoodul on lõimede loomise kaasaegne standard.
  • Loo lõime: Laienda Thread klassi, tühista __init__ ja run(), seejärel kutsu käivitamiseks välja start() ja oota lõpetamist join() abil.
  • 🧪 Vältige võistlustingimusi: Lukustus lubab korraga ainult ühel lõimel kriitilisse sektsiooni siseneda, vältides ummikseisu ja jagatud andmete rikkumist.
  • 🛠️ Saage aru GIL-ist: Globaalse interpretaatori lukk lubab ühe lõime käivitada Python baitkoodi korraga, seega vajab protsessoriga seotud töö mitmekordset töötlemist.
  • 🤖 Tehisintellekti töökoormused: Mitmekeermeline töötlemine kiirendab sisend-/väljundiga seotud tehisintellekti samme, näiteks andmete laadimist, samas kui NumPy ja PyTorch vabastab GIL-i paralleelarvutuste jaoks.

Mitme lõime sisse lülitamine Python

. Python programmeerimiskeel võimaldab teil kasutada mitmeprotsessorilist või mitmekeermelist töötlemist. Selles õpetuses õpite, kuidas kirjutada mitmekeermelisi rakendusi Python.

Mis on lõim?

Lõim on samaaegse programmeerimise täitmisüksus. Mitmelõimlikkus on tehnika, mis võimaldab protsessoril täita ühe protsessi paljusid ülesandeid samaaegselt. Need lõimed saavad töötada individuaalselt, jagades samal ajal oma protsessiressursse.

Mis on protsess?

Protsess on põhimõtteliselt täidetav programm. Kui käivitate arvutis rakenduse (nt brauseri või tekstiredaktori), loob operatsioonisüsteem protsessi.

Mis on multithreading Python?

Mitme lõime sisse lülitamine Python Programmeerimine on tuntud tehnika, mille puhul protsessi mitu lõime jagavad oma andmeruumi põhilõimega, mis muudab lõimede sees teabe jagamise ja suhtluse lihtsaks ja tõhusaks. Lõimed on protsessidest kergemad. Mitu lõime võivad töötada individuaalselt, jagades samal ajal oma protsessiressursse. Mitmelõimelisuse eesmärk on käivitada mitu ülesannet ja funktsiooni korraga.

Mis on multitöötlus?

Mitmeprotsessiline töötlemine võimaldab korraga käivitada mitut sõltumatut protsessi. Need protsessid ei jaga oma ressursse ja suhtlevad IPC kaudu.

Python Mitmelõimeline vs mitmetöötlus

Protsesside ja lõimede mõistmiseks kujutage ette järgmist stsenaariumi: teie arvutis olev .exe-fail on programm. Selle avamisel laadib operatsioonisüsteem selle mällu ja protsessor käivitab selle. Praegu töötavat programmi eksemplari nimetatakse protsessiks.

Igal protsessil on kaks põhikomponenti:

  • . Code
  • Andmed

Nüüd võib protsess sisaldada ühte või mitut alamosa, mida nimetatakse niidid. See sõltub operatsioonisüsteemi arhitektuurist. Lõime võib mõelda kui protsessi osa, mida operatsioonisüsteem saab eraldi käivitada.

Teisisõnu, see on käskude voog, mida operatsioonisüsteem saab iseseisvalt käivitada. Ühe protsessi lõimed jagavad selle protsessi andmeid ja on loodud töötama koos, et hõlbustada paralleelsust.

Miks kasutada Multithreadingut?

Multithreading võimaldab jagada rakenduse mitmeks alamülesandeks ja käivitada neid ülesandeid samaaegselt. Kui kasutate mitut lõime õigesti, saab teie rakenduse kiirust, jõudlust ja renderdamist parandada.

Python Mitmikeermeline

Python toetab nii mitmetöötluslikke kui ka mitmekeermelisi konstruktsioone. Selles õpetuses keskendute peamiselt rakendamisele mitmelõimeline rakendused koos PythonLõimede haldamiseks on kaks peamist moodulit Python:

  1. . niit moodul ja
  2. . keermestamine moodul

Kuid aastal Python, on olemas ka nn globaalne interpreteri lukk (GIL). See ei võimalda jõudlust oluliselt suurendada ja võib isegi vähendama mõne mitme lõimega rakenduse jõudlus. Sellest kõigest saate teada selle õpetuse tulevastest osadest.

Keerme ja lõime moodulid

Kaks moodulit, mille kohta selles õpetuses tutvute, on keerme moodul ja keermestusmoodul.

Keermemoodul on aga juba ammu aegunud. Alustades sellest Python 3, see on määratud aegunuks ja on juurdepääsetav ainult kui _lõim tagasiühilduvuse tagamiseks.

Peaksite kasutama kõrgemat taset keermestamine moodul rakenduste jaoks, mida kavatsete juurutada. Lõimemoodulit on siin käsitletud ainult hariduslikel eesmärkidel.

Keerme moodul

Selle mooduli abil uue lõime loomise süntaks on järgmine:

thread.start_new_thread(function_name, arguments)

Olgu, nüüd olete kodeerimise alustamiseks katnud põhiteooria. Niisiis, avage oma IDLE või märkmikusse ja tippige järgmine tekst:

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))

Salvestage fail ja vajutage programmi käivitamiseks klahvi F5. Kui kõik tehti õigesti, peaksite nägema järgmist väljundit:

Keerme moodul

Järgmistes osades saate teada rohkem võistlustingimuste ja nendega toimetuleku kohta.

Keerme moodul

KOODI SELGITUS

  1. Need laused impordivad aja- ja lõimemooduli, mida kasutatakse käskude täitmise ja edasilükkamise haldamiseks. Python niidid.
  2. Siin olete määratlenud funktsiooni nimega thread_test, mida kutsutakse start_new_thread meetod. Funktsioon käivitab neli iteratsiooni kestva while-tsükli ja prindib välja kutsunud lõime nime. Kui iteratsioon on lõppenud, prindib see teate, mis ütleb, et lõim on täitmise lõpetanud.
  3. See on teie programmi põhiosa. Siin helistate lihtsalt start_new_thread meetodiga lõime_test funktsioon argumendina. See loob argumendina edastatud funktsioonile uue lõime ja hakkab seda käivitama. Pane tähele, et saad selle (thread_test) asendada mis tahes muu funktsiooniga, mida soovid lõimena käivitada.

Keermestamise moodul

See moodul on lõimestamise kõrgetasemeline implementatsioon Python ja mitmelõimeliste rakenduste haldamise de facto standard. See pakub võrreldes lõimemooduliga laia valikut funktsioone.

Keermestamise mooduli struktuur

Keermestamise mooduli struktuur

Siin on nimekiri mõnest selles moodulis määratletud kasulikest funktsioonidest:

Funktsiooni nimi Kirjeldus
activeCount() Tagastab arvu Keere esemeid, mis on endiselt elus.
currentThread() Tagastab klassi Thread praeguse objekti.
loetlema () Loetleb kõik aktiivsed lõimeobjektid.
isDaemon() Tagastab tõene, kui lõim on deemon.
on elus() Tagastab tõe, kui niit on veel elus.
Lõim klassi meetodid
start () Alustab lõime tegevust. Seda tuleb iga lõime jaoks kutsuda ainult üks kord, kuna mitmekordsel kutsumisel ilmneb käitustõrge.
jooksma () See meetod tähistab lõime aktiivsust ja seda saab alistada klass, mis laiendab lõime klassi.
liitu () See blokeerib muu koodi täitmise, kuni lõim, millel meetodit join() kutsuti, lõpetatakse.

Taustalugu: lõime klass

Enne kui hakkate mitmelõimeliste programmide kodeerimisega alustama lõimemooduli abil, on oluline mõista lõimeklassi. Lõimeklass on peamine klass, mis määratleb lõime malli ja toimingud. Python.

Kõige levinum viis mitmekeermelise süsteemi loomiseks Python Rakenduse eesmärk on deklareerida klass, mis laiendab Thread klassi ja tühistab selle run() meetodi.

Kokkuvõttes tähistab klass Thread koodijada, mis jookseb eraldi niit kontroll.

Nii et mitme lõimega rakenduse kirjutamisel teete järgmist.

  1. defineeri klass, mis laiendab Thread klassi
  2. Alistage __init__ konstruktor
  3. Alistage jooksma () meetod

Kui niidiobjekt on tehtud, siis start () meetodit saab kasutada selle tegevuse elluviimise alustamiseks ja liitu () meetodit saab kasutada kogu muu koodi blokeerimiseks kuni praeguse tegevuse lõpuni.

Proovime nüüd eelmise näite rakendamiseks kasutada lõimemoodulit. Käivitage uuesti oma IDLE ja sisestage järgmine tekst:

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()

See on väljund, kui käivitate ülaltoodud koodi:

Taustalugu: lõime klass

KOODI SELGITUS

Taustalugu: lõime klass

  1. See osa on sama mis meie eelmine näide. Siin impordite aja- ja lõimemooduli, mida kasutatakse toimingu täitmise ja viivituste haldamiseks. Python niidid.
  2. Selles bitis loote klassi nimega threadtester, mis pärib või laiendab Keere keermestusmooduli klass. See on üks levinumaid viise lõimede loomiseks PythonSiiski peaksite tühistama ainult konstruktori ja jooksma () meetodit oma rakenduses. Nagu näete ülaltoodud koodinäidisest, __init__ meetod (konstruktor) on alistatud. Samamoodi olete alistanud ka jooksma () meetod. See sisaldab koodi, mida soovite lõimes käivitada. Selles näites olete kutsunud funktsiooni thread_test().
  3. See on thread_test() meetod, mis võtab väärtuse i argumendina, vähendab seda igal iteratsioonil 1 võrra ja kordab ülejäänud koodi, kuni i saab 0. Igas iteratsioonis prindib see parajasti töötava lõime nime ja magab ooterežiimis sekundit (mida võetakse samuti argumendina).
  4. thread1 = threadtester(1, “First Thread”, 1) Siin loome lõime ja edastame kolm parameetrit, mille deklareerisime failis __init__. Esimene parameeter on lõime id, teine ​​parameeter on lõime nimi ja kolmas parameeter on loendur, mis määrab, mitu korda while tsükkel peaks jooksma.
  5. thread2.start() Meetodit start kasutatakse lõime täitmise alustamiseks. Sisemiselt kutsub funktsioon start() teie klassi meetodit run().
  6. thread3.join() Meetod join() blokeerib muu koodi täitmise ja ootab, kuni lõim, millel seda kutsuti, lõpeb.

Nagu te juba teate, on samas protsessis olevatel lõimedel juurdepääs selle protsessi mälule ja andmetele. Seetõttu, kui rohkem kui üks lõim proovib andmeid samaaegselt muuta või neile juurde pääseda, võivad tekkida vead.

Järgmises osas näete erinevaid tüsistusi, mis võivad ilmneda, kui lõimed pääsevad andmetele ja kriitilisele osale juurde ilma olemasolevaid juurdepääsutehinguid kontrollimata.

Ummikseisud ja võistlustingimused

Enne ummikseisude ja võidujooksutingimuste tundmaõppimist on kasulik mõista mõnda samaaegse programmeerimisega seotud põhimõistet:

  • Kriitiline osa: See on koodifragment, mis pääseb juurde jagatud muutujatele või muudab neid ning mida tuleb teostada aatomitehinguna.
  • Konteksti vahetamine: See on protsess, mida protsessor järgib lõime oleku salvestamiseks enne ühelt ülesandelt teisele üleminekut, et seda saaks hiljem samast kohast jätkata.

Ummikud

Ummikud on kõige kardetumad probleemid, millega arendajad samaaegsete/mitmelõimeliste rakenduste kirjutamisel silmitsi seisavad PythonPattseisude mõistmiseks on parim viis kasutada klassikalist arvutiteaduse näidisülesannet, mida tuntakse nime all Söögi- Philosophers Probleem.

Söögifilosoofide probleemipüstitus on järgmine:

Viis filosoofi istuvad ümara laua taga, millel on viis taldrikut spagette (teatud tüüpi pasta) ja viis kahvlit, nagu joonisel näidatud.

Söögi- Philosophers Probleem

Söögi- Philosophers Probleem

Filosoof peab igal ajahetkel kas sööma või mõtlema.

Veelgi enam, filosoof peab võtma kaks temaga külgnevat kahvlit (st vasaku ja parema kahvli), enne kui ta saab spagette süüa. Ummikuprobleem tekib siis, kui kõik viis filosoofi võtavad korraga oma õiged kahvlid.

Kuna igal filosoofil on üks kahvel, ootavad nad kõik, kuni teised kahvli maha panevad. Selle tulemusena ei saa ükski neist spagette süüa.

Samamoodi tekib samaaegses süsteemis ummik, kui erinevad lõimed või protsessid (filosoofid) üritavad korraga omandada jagatud süsteemiressursse (kahvleid). Selle tulemusena ei saa ükski protsess käivitada, kuna nad ootavad mõnda muud ressurssi, mida hoiab mõni muu protsess.

Võistlustingimused

Võidujooksutingimus on programmi soovimatu olek, mis tekib siis, kui süsteem sooritab samaaegselt kahte või enamat toimingut. Näiteks vaatleme seda lihtsat for-tsüklit:

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

Kui loote n Kui koodi käitab korraga mitu lõime, ei saa te määrata i väärtust (mida lõimed jagavad), kui programm on käivitatud. Selle põhjuseks on asjaolu, et reaalses mitmelõimelises keskkonnas võivad lõimed kattuda ja lõime poolt hangitud ja muudetud i väärtus võib vahepeal muutuda, kui mõni teine ​​lõim sellele juurde pääseb.

Need on kaks peamist probleemide klassi, mis võivad mitmekeermelises või hajutatud keskkonnas esineda Python rakendus. Järgmises osas saate teada, kuidas seda probleemi lõimede sünkroonimise abil lahendada.

Synchroniseerivad niidid

Võistlustingimuste, ummikseisude ja muude keermepõhiste probleemide lahendamiseks pakub keermestusmoodul järgmist lukk objektiks. Idee seisneb selles, et kui lõim soovib juurdepääsu konkreetsele ressursile, omandab see selle ressursi lukustuse. Kui lõim lukustab teatud ressursi, ei pääse ükski teine ​​lõim sellele juurde enne, kui lukk on vabastatud. Selle tulemusena on muudatused ressursis tuumakad ja rassitingimused välditakse.

Lukk on madala taseme sünkroonimisprimitiiv, mille on rakendanud _lõim moodul. Igal ajahetkel võib lukk olla ühes kahest olekust: lukus or lukustamata. See toetab kahte meetodit:

  1. omandama(): Kui lukustusolek on avatud, muudab meetodi acquire() kutsumine oleku lukustatud ja tagastab väärtuse. Kui aga olek on lukus, blokeeritakse meetodi acquire() kutsumine seni, kuni mõni teine ​​lõim kutsub meetodi release() välja.
  2. vabastamine(): Release() meetodit kasutatakse oleku määramiseks lukustamata, st luku vabastamiseks. Seda saab kutsuda mis tahes lõimega, mitte tingimata sellega, mis luku omandas.

Siin on näide lukkude kasutamisest rakendustes. Käivitage oma IDLE ja tippige järgmine:

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()

Nüüd vajuta F5. Peaksite nägema sellist väljundit:

Synchroniseerivad lõimed

KOODI SELGITUS

Synchroniseerivad lõimed

  1. Siin loote lihtsalt uue luku, helistades numbrile keermestamine.Lock() tehase funktsioon. Sisemiselt tagastab Lock() kõige tõhusama konkreetse lukustusklassi eksemplari, mida platvorm hooldab.
  2. Esimeses lauses omandate luku, kutsudes välja hankimismeetodi. Kui lukk on antud, printige "Lukk omandatud" konsooli juurde. Kui kogu kood, mida soovite lõime käivitada, on täitmise lõpetanud, vabastate lukustuse, kutsudes välja meetodi release().

Teooria on hea, aga kuidas sa tead, et lukk tegelikult töötas? Kui vaatad väljundit, näed, et iga print-lause prindib korraga täpselt ühe rea. Tuleta meelde, et varasemas näites olid print-funktsiooni väljundid juhuslikud, kuna mitu lõime kasutasid print() meetodit korraga. Siin kutsutakse print-funktsiooni alles pärast luku saavutamist. Seega kuvatakse väljundeid ükshaaval ja rida-realt.

Lisaks lukkudele, Python toetab ka mõningaid teisi lõimede sünkroniseerimise mehhanisme, mis on loetletud allpool:

  1. RLukud
  2. Semaphores
  3. Tingimused
  4. Sündmused ja
  5. Piirded

Global Interpreter Lock (ja kuidas sellega toime tulla)

Enne detailidesse laskumist PythonGIL-i puhul defineerime mõned terminid, mis on kasulikud järgmise osa mõistmiseks:

  1. Protsessoriga seotud kood: see viitab mis tahes koodijupile, mida protsessor otse täidab.
  2. I/O-ga seotud kood: see võib olla mis tahes kood, mis pääseb failisüsteemile juurde operatsioonisüsteemi kaudu.
  3. CPython: see on viide täitmine of Python ja seda saab kirjeldada kui tõlgi, mis on kirjutatud C ja Python (programmeerimiskeel).

Milles GIL on Python?

Global Interpreter Lock (GIL) in Python on protsessilukk või mutex, mida kasutatakse protsessidega tegelemisel. See tagab, et üks lõim pääseb korraga juurde konkreetsele ressursile ja takistab ka objektide ja baitkoodide samaaegset kasutamist. See toob kasu ühelõimelistele programmidele jõudluse suurenemise näol. GIL Python on väga lihtne ja kergesti rakendatav.

Luku abil saab tagada, et teatud ressursile on teatud ajahetkel juurdepääs ainult ühel lõimel.

Üks omadusi Python on see, et see kasutab iga interpreteerimisprotsessi jaoks globaalset lukku, mis tähendab, et iga protsess käsitleb seda Python tõlk ise kui ressurss.

Näiteks oletame, et olete kirjutanud Python programm, mis kasutab nii protsessori kui ka sisend-/väljundoperatsioonide teostamiseks kahte lõime. Selle programmi käivitamisel juhtub järgmine:

  1. . Python Tõlkija loob uue protsessi ja käivitab lõimed.
  2. Kui lõime 1 hakkab tööle, omandab see esmalt GIL-i ja lukustab selle.
  3. Kui lõime 2 soovib praegu käivitada, peab see ootama GIL-i vabastamist, isegi kui mõni teine ​​​​protsessor on vaba.
  4. Oletame nüüd, et lõime-1 ootab I/O toimingut. Sel ajal vabastab see GIL-i ja lõime-2 omandab selle.
  5. Kui lõime 1 soovib pärast I/O operatsioonide lõpetamist kohe käivituda, peab see taas ootama, kuni lõime 2 vabastab GIL-i.

Seetõttu saab interpreterile igal ajahetkel ligi pääseda ainult üks lõim, mis tähendab, et korraga töötab ainult üks lõim. Python kood antud ajahetkel.

Ühetuumalise protsessori puhul on see okei, kuna see kasutaks lõimede haldamiseks ajalõikamist (vt selle õpetuse esimest osa). Mitmetuumaliste protsessorite puhul on aga mitmel lõimel töötaval protsessoriga seotud funktsioonil programmi efektiivsusele märkimisväärne mõju, kuna see ei kasuta tegelikult kõiki saadaolevaid südamikke korraga.

Miks oli GIL-i vaja?

CPython prügikoguja kasutab tõhusat mäluhalduse tehnikat, mida tuntakse viidete loendamise nime all. See toimib järgmiselt: iga objekt Python omab viitearvu, mis suureneb, kui see määratakse uuele muutuja nimele või lisatakse konteinerisse (nt tupled, loendid jne). Samamoodi väheneb viidete arv, kui viide väljub ulatusest või kui kutsutakse välja del-lause. Kui objekti viitearvu jõuab nullini, kogutakse see prügiks ja eraldatud mälu vabastatakse.

Probleem on aga selles, et viitearvu muutuja on nagu iga teine ​​globaalne muutuja altid võidujooksu tingimustele. Selle probleemi lahendamiseks arendajad Python otsustasid kasutada globaalset interpretaatori lukku. Teine võimalus oli lisada igale objektile lukk, mis oleks toonud kaasa ummikseisud ja suurendanud üldkulu acquire() ja release() kõnede tõttu.

Seega on GIL mitmekeermelise protsessi jaoks oluline piirang. Python programmid, mis käitavad palju protsessori koormust nõudvaid toiminguid (mis muudab need sisuliselt ühelõimelisteks). Kui soovite oma rakenduses kasutada mitut protsessori tuuma, kasutage multitöötlus mooduli asemel.

KKK

Kasutage lõimetöötlust sisend-/väljundkoormusega tööde jaoks, näiteks võrgukõned, failidele juurdepääs või andmebaasipäringud, kus lõimed ootavad väliseid ressursse. Kasutage mitmeprotsessorilist töötlemist protsessoriga seotud tööde jaoks, näiteks mahukate arvutuste jaoks, kuna see töötab mitmel tuumal ja möödub GIL-ist.

Mitte vaikimisi. PEP 703 tutvustas valikulist vabakeermelist ehitust. Python 3.13, mis keelab GIL-i ja Python Versioonis 3.14 jätkatakse sellega. Standardsetes versioonides on GIL endiselt saadaval, seega enamik programme töötab edasi täpselt nagu varem.

Deemoni lõim töötab taustal ega blokeeri programmi väljumist. Kui alles on ainult deemoni lõimed, Python lülitab need välja ja lõpetab töö. Määrake üks enne start() kutsumist funktsiooniga thread.daemon = True.

Klass Thread ei tagasta funktsiooni run() tulemust otse. Salvesta väärtus thread-objektile või jagatud järjekorda või kasuta funktsiooni concurrent.futures.ThreadPoolExecutor, mille submit() meetod tagastab funktsiooni result() abil loetud Future'i.

ThreadPoolExecutor on kõrgetasemeline abimees, mis haldab teie eest töölõimede kogumit. Ülesandeid saab esitada submit() või map() abil ning see tegeleb lõimede loomise, taaskasutamise ja puhastamisega, tagastades iga tulemust sisaldavaid Future objekte.

Saate luua sadu või tuhandeid lõime, kuid GIL laseb käivitada ainult ühe Python baitkoodi igal hetkel. Need kattuvad I/O ooteaegadel endiselt, seega aitavad paljud samaaegsed lõimed I/O-ga seotud programme palju rohkem kui protsessoriga seotud programme.

Jah, peamiselt sisend-/väljundiga seotud sammude jaoks, näiteks andmete laadimine, API-de kutsumine või failide lugemine. Tugev treenimine on protsessoriga seotud, seega teegid nagu NumPy ja PyTorch vabastab GIL-i C-koodis või tugineb tõelise paralleelsuse saavutamiseks mitmetöötlusele.

Jah. GitHub Copilot täidab kommentaari või funktsiooni nime põhjal automaatselt levinud mustreid, näiteks lõime alamklasse, lukkude kasutamist ja ThreadPoolExecutori seadistusi. Enne genereeritud koodile lootmist vaadake see alati üle võidujooksu tingimuste ja õige lukustuskäitluse osas.

Võta see postitus kokku järgmiselt: