Cum să vă îmbunătățiți codul Python cu concurență și paralelism

Recomandări cheie

  • Concurența și paralelismul sunt principii fundamentale ale executării sarcinilor în calcul, fiecare având caracteristicile sale distincte.
  • Concurența permite utilizarea eficientă a resurselor și o capacitate de răspuns îmbunătățită a aplicațiilor, în timp ce paralelismul este crucial pentru performanță și scalabilitate optime.
  • Python oferă opțiuni pentru gestionarea concurenței, cum ar fi threading și programare asincronă cu asyncio, precum și paralelism folosind modulul de multiprocesare.

Concurența și paralelismul sunt două tehnici care vă permit să rulați mai multe programe simultan. Python are mai multe opțiuni pentru gestionarea sarcinilor concomitent și în paralel, ceea ce poate fi confuz.

Explorați instrumentele și bibliotecile disponibile pentru implementarea corectă a concurenței și paralelismului în Python și a modului în care acestea diferă.

Înțelegerea concurenței și paralelismului

Concurența și paralelismul se referă la două principii fundamentale ale executării sarcinilor în calcul. Fiecare are caracteristicile sale distincte.

  • Concurența este capacitatea unui program de a gestiona mai multe sarcini în același timp, fără a le executa neapărat exact în același timp. Se învârte în jurul ideii de intercalare a sarcinilor, comutând între ele într-un mod care pare simultan.
  • Paralelismul, pe de altă parte, implică executarea mai multor sarcini în mod real în paralel. De obicei, profită de mai multe nuclee sau procesoare CPU. Paralelismul realizează o execuție simultană reală, permițându-vă să efectuați sarcini mai rapid și este potrivit pentru operațiuni intensive din punct de vedere computațional.
  •   Cum să vă ștergeți permanent contul ICQ

    Importanța concurenței și a paralelismului

    Necesitatea concurenței și paralelismului în calcul nu poate fi exagerată. Iată de ce sunt importante aceste tehnici:

  • Utilizarea resurselor: concurența permite utilizarea eficientă a resurselor sistemului, asigurându-se că sarcinile progresează în mod activ, mai degrabă decât să aștepte fără probleme resurse externe.
  • Capacitatea de reacție: concurența poate îmbunătăți capacitatea de răspuns a aplicațiilor, în special în scenariile care implică interfețe de utilizator sau servere web.
  • Performanță: Paralelismul este crucial pentru obținerea performanței optime, în special în sarcinile legate de CPU, cum ar fi calcule complexe, procesarea datelor și simulări.
  • Scalabilitate: Atât concurența, cât și paralelismul sunt esențiale pentru construirea de sisteme scalabile.
  • Pregătire pentru viitor: Pe măsură ce tendințele hardware continuă să favorizeze procesoarele multicore, capacitatea de a valorifica paralelismul va deveni din ce în ce mai necesară.
  • Concurență în Python

    Puteți obține concurență în Python folosind threading și programare asincronă cu biblioteca asyncio.

    Threading în Python

    Threadingul este un mecanism de concurență Python care vă permite să creați și să gestionați sarcini într-un singur proces. Threadurile sunt potrivite pentru anumite tipuri de sarcini, în special cele care sunt legate de I/O și pot beneficia de execuția concomitentă.

    Modulul de threading al lui Python oferă o interfață de nivel înalt pentru crearea și gestionarea thread-urilor. În timp ce GIL (Global Interpreter Lock) limitează firele de execuție în termeni de paralelism real, ele pot totuși să obțină concurență prin intercalarea eficientă a sarcinilor.

    Codul de mai jos arată un exemplu de implementare a concurenței folosind fire. Utilizează biblioteca de solicitări Python pentru a trimite o solicitare HTTP, o sarcină comună de blocare a I/O. De asemenea, utilizează modulul de timp pentru a calcula timpul de execuție.

     import requests
    import time
    import threading

    urls = [
        'https://www.google.com',
        'https://www.wikipedia.org',
        'https://www.makeuseof.com',
    ]


    def download_url(url):
        response = requests.get(url)
        print(f"Downloaded {url} - Status Code: {response.status_code}")


    start_time = time.time()

    for url in urls:
        download_url(url)

    end_time = time.time()
    print(f"Sequential download took {end_time - start_time:.2f} seconds\n")


    start_time = time.time()
    threads = []

    for url in urls:
        thread = threading.Thread(target=download_url, args=(url,))
        thread.start()
        threads.append(thread)


    for thread in threads:
        thread.join()

    end_time = time.time()
    print(f"Threaded download took {end_time - start_time:.2f} seconds")

    Rulând acest program, ar trebui să vedeți cât de mai rapide sunt cererile threaded decât cererile secvențiale. Deși diferența este doar o fracțiune de secundă, obțineți o idee clară a îmbunătățirii performanței atunci când utilizați fire pentru activități legate de I/O.

      11 cele mai bune instrumente de codare/programare în pereche pentru echipa ta de dezvoltare

    Programare asincronă cu Asyncio

    asincron oferă o buclă de evenimente care gestionează sarcini asincrone numite coroutine. Coroutinele sunt funcții pe care le puteți întrerupe și relua, făcându-le ideale pentru sarcini legate de I/O. Biblioteca este utilă în special pentru scenariile în care sarcinile implică așteptarea resurselor externe, cum ar fi solicitările de rețea.

    Puteți modifica exemplul anterior de trimitere a cererii pentru a lucra cu asyncio:

     import asyncio
    import aiohttp
    import time

    urls = [
        'https://www.google.com',
        'https://www.wikipedia.org',
        'https://www.makeuseof.com',
    ]


    async def download_url(url):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                content = await response.text()
                print(f"Downloaded {url} - Status Code: {response.status}")


    async def main():
        
        tasks = [download_url(url) for url in urls]

        
        await asyncio.gather(*tasks)

    start_time = time.time()


    asyncio.run(main())

    end_time = time.time()

    print(f"Asyncio download took {end_time - start_time:.2f} seconds")

    Folosind codul, puteți descărca pagini web simultan folosind asyncio și puteți profita de operațiunile I/O asincrone. Acest lucru poate fi mai eficient decât threading-ul pentru sarcini legate de I/O.

    Paralelism în Python

    Puteți implementa paralelismul folosind Modulul de multiprocesare al lui Pythoncare vă permite să profitați din plin de procesoarele multicore.

    Multiprocesare în Python

    Modulul de multiprocesare al lui Python oferă o modalitate de a realiza paralelismul prin crearea de procese separate, fiecare cu propriul interpret Python și spațiu de memorie. Acest lucru ocolește în mod eficient Blocarea globală a interpretului (GIL), făcându-l potrivit pentru sarcini legate de CPU.

     import requests
    import multiprocessing
    import time

    urls = [
        'https://www.google.com',
        'https://www.wikipedia.org',
        'https://www.makeuseof.com',
    ]


    def download_url(url):
        response = requests.get(url)
        print(f"Downloaded {url} - Status Code: {response.status_code}")

    def main():
        
        num_processes = len(urls)
        pool = multiprocessing.Pool(processes=num_processes)

        start_time = time.time()
        pool.map(download_url, urls)
        end_time = time.time()

        
        pool.close()
        pool.join()

        print(f"Multiprocessing download took {end_time-start_time:.2f} seconds")

    main()

    În acest exemplu, multiprocesarea generează mai multe procese, permițând funcției download_url să ruleze în paralel.

      11 Cel mai bun software de management al activelor digitale pentru orice afacere

    Când să folosiți concurența sau paralelismul

    Alegerea între concurență și paralelism depinde de natura sarcinilor dvs. și de resursele hardware disponibile.

    Puteți utiliza concurența atunci când aveți de-a face cu sarcini legate de I/O, cum ar fi citirea și scrierea în fișiere sau efectuarea de solicitări de rețea și atunci când constrângerile de memorie sunt o problemă.

    Utilizați multiprocesarea atunci când aveți sarcini legate de CPU care pot beneficia de un paralelism real și atunci când aveți o izolare robustă între sarcini, unde eșecul unei sarcini nu ar trebui să le afecteze pe altele.

    Profită de concurență și paralelism

    Paralelismul și concurența sunt modalități eficiente de îmbunătățire a capacității de răspuns și a performanței codului dvs. Python. Este important să înțelegeți diferențele dintre aceste concepte și să alegeți cea mai eficientă strategie.

    Python oferă instrumentele și modulele de care aveți nevoie pentru a vă face codul mai eficient prin concurență sau paralelism, indiferent dacă lucrați cu procese legate de CPU sau legate de I/O.