Jak ulepszyć swój kod Pythona dzięki współbieżności i równoległości

  • Współbieżność i równoległość to podstawowe zasady wykonywania zadań w informatyce, a każda z nich ma swoją odrębną charakterystykę.
  • Współbieżność pozwala na efektywne wykorzystanie zasobów i lepszą responsywność aplikacji, natomiast równoległość jest kluczowa dla optymalnej wydajności i skalowalności.
  • Python zapewnia opcje obsługi współbieżności, takie jak wielowątkowość i programowanie asynchroniczne z asyncio, a także równoległość przy użyciu modułu wieloprocesorowego.

Współbieżność i równoległość to dwie techniki umożliwiające jednoczesne uruchamianie kilku programów. Python oferuje wiele opcji jednoczesnej i równoległej obsługi zadań, co może być mylące.

Poznaj narzędzia i biblioteki dostępne do prawidłowego wdrażania współbieżności i równoległości w Pythonie oraz różnice między nimi.

Zrozumienie współbieżności i równoległości

Współbieżność i równoległość odnoszą się do dwóch podstawowych zasad wykonywania zadań w informatyce. Każdy ma swoje odrębne cechy.

  • Współbieżność to zdolność programu do jednoczesnego zarządzania wieloma zadaniami, bez konieczności wykonywania ich dokładnie w tym samym czasie. Opiera się na idei przeplatania zadań, przełączania się między nimi w sposób sprawiający wrażenie jednoczesnego.
  • Z drugiej strony równoległość polega na wykonywaniu wielu zadań rzeczywiście równolegle. Zwykle wykorzystuje wiele rdzeni lub procesorów procesora. Równoległość zapewnia prawdziwie jednoczesne wykonanie, umożliwiając szybsze wykonywanie zadań i dobrze nadaje się do operacji wymagających intensywnych obliczeń.
  • Znaczenie współbieżności i równoległości

    Nie można przecenić potrzeby współbieżności i równoległości w informatyce. Oto dlaczego te techniki są tak ważne:

  • Wykorzystanie zasobów: Współbieżność pozwala na efektywne wykorzystanie zasobów systemowych, zapewniając, że zadania aktywnie wykonują postęp, a nie bezczynnie czekają na zasoby zewnętrzne.
  • Responsywność: Współbieżność może poprawić responsywność aplikacji, szczególnie w scenariuszach obejmujących interfejsy użytkownika lub serwery internetowe.
  • Wydajność: Równoległość ma kluczowe znaczenie dla osiągnięcia optymalnej wydajności, szczególnie w zadaniach wymagających procesora, takich jak złożone obliczenia, przetwarzanie danych i symulacje.
  • Skalowalność: zarówno współbieżność, jak i równoległość są niezbędne do budowania skalowalnych systemów.
  • Przyszłościowe rozwiązania: Ponieważ trendy sprzętowe w dalszym ciągu faworyzują procesory wielordzeniowe, możliwość wykorzystania równoległości będzie coraz bardziej konieczna.
  • Współbieżność w Pythonie

    Współbieżność w Pythonie można osiągnąć za pomocą wątków i programowania asynchronicznego za pomocą biblioteki asyncio.

    Threading w Pythonie

    Threading to mechanizm współbieżności w języku Python, który umożliwia tworzenie zadań i zarządzanie nimi w ramach jednego procesu. Wątki nadają się do niektórych typów zadań, szczególnie tych związanych z operacjami we/wy i mogą czerpać korzyści ze współbieżnego wykonywania.

    Moduł wątków Pythona zapewnia interfejs wysokiego poziomu do tworzenia wątków i zarządzania nimi. Chociaż GIL (Global Interpreter Lock) ogranicza wątki pod względem prawdziwej równoległości, nadal mogą one osiągnąć współbieżność poprzez efektywne przeplatanie zadań.

    Poniższy kod przedstawia przykładową implementację współbieżności przy użyciu wątków. Wykorzystuje bibliotekę żądań Pythona do wysyłania żądania HTTP, co jest typowym zadaniem blokowania we/wy. Wykorzystuje również moduł czasu do obliczenia czasu wykonania.

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

    Uruchamiając ten program, powinieneś zobaczyć, o ile szybsze są żądania wątkowe niż żądania sekwencyjne. Chociaż różnica to tylko ułamek sekundy, można wyraźnie zauważyć poprawę wydajności podczas używania wątków do zadań związanych z we/wy.

    Programowanie asynchroniczne za pomocą Asynccio

    asyncio udostępnia pętlę zdarzeń, która zarządza zadaniami asynchronicznymi zwanymi współprogramami. Współprogramy to funkcje, które można wstrzymywać i wznawiać, co czyni je idealnymi do zadań związanych z we/wy. Biblioteka jest szczególnie przydatna w scenariuszach, w których zadania wymagają oczekiwania na zasoby zewnętrzne, takie jak żądania sieciowe.

    Możesz zmodyfikować poprzedni przykład wysyłania żądań, aby działał z 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")

    Używając kodu, możesz jednocześnie pobierać strony internetowe za pomocą asyncio i korzystać z asynchronicznych operacji we/wy. Może to być bardziej wydajne niż wątki w przypadku zadań związanych z we/wy.

    Równoległość w Pythonie

    Możesz zaimplementować równoległość za pomocą Moduł wieloprocesorowy Pythonaco pozwala w pełni wykorzystać możliwości procesorów wielordzeniowych.

    Wieloprocesorowość w Pythonie

    Moduł wieloprocesowy Pythona umożliwia osiągnięcie równoległości poprzez utworzenie oddzielnych procesów, każdy z własnym interpreterem Pythona i przestrzenią pamięci. To skutecznie omija globalną blokadę interpretera (GIL), dzięki czemu nadaje się do zadań związanych z procesorem.

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

    W tym przykładzie przetwarzanie wieloprocesowe powoduje uruchomienie wielu procesów, umożliwiając równoległe działanie funkcji download_url.

    Kiedy używać współbieżności lub równoległości

    Wybór pomiędzy współbieżnością a równoległością zależy od charakteru zadań i dostępnych zasobów sprzętowych.

    Współbieżności można używać podczas wykonywania zadań związanych z we/wy, takich jak odczytywanie i zapisywanie plików lub wysyłanie żądań sieciowych, a także gdy problemem są ograniczenia pamięci.

    Używaj przetwarzania wieloprocesowego, jeśli masz zadania powiązane z procesorem, które mogą skorzystać na prawdziwej równoległości, i gdy masz solidną izolację między zadaniami, gdzie awaria jednego zadania nie powinna mieć wpływu na inne.

    Wykorzystaj współbieżność i równoległość

    Równoległość i współbieżność to skuteczne sposoby poprawy responsywności i wydajności kodu Pythona. Ważne jest, aby zrozumieć różnice między tymi koncepcjami i wybrać najskuteczniejszą strategię.

    Python oferuje narzędzia i moduły potrzebne do zwiększenia efektywności kodu poprzez współbieżność lub równoległość, niezależnie od tego, czy pracujesz z procesami związanymi z procesorem, czy związanymi z we/wy.