A párhuzamos feladatvégrehajtás két módszerének összehasonlítása: a többszálú és a több feldolgozás Pythonban.

Ha nagyszámú végrehajtandó feladattal foglalkozunk, akkor inkább ne legyen szekvenciális feladatvégrehajtás, mivel ez egy hosszú, lassú és meglehetősen unalmas folyamat. Ehelyett azt szeretnénk, ha programunk egyszerre indítaná el az összes feladatot, hogy azok egymás mellett végezhetők legyenek.

A párhuzamosság vagy a párhuzamos feladatvégrehajtás nem új fogalom, és a legtöbb fő nyelven támogatott. A Python nem különbözik egymástól, és egy elég ügyes modult biztosít, amely könnyen használható feladatok párhuzamos vagy párhuzamos futtatására. Ebben a cikkben az a célom, hogy rövid áttekintést nyújtsak a többszálas és többfeldolgozási folyamatról a pythonban, és mindkettő teljesítményét összehasonlítom. A cikk a következő témákkal foglalkozik:

  • A párhuzamosság és a párhuzamosság közötti különbség.
  • Multi-threading Pythonban.
  • Többszörös feldolgozás Pythonban.
  • Benchmarking Multi-Treading és Multi-Processing.
  • Melyik módszer melyik programhoz jobb.

A párhuzamosság és a párhuzamosság közötti különbség

Az egyidejűség és a párhuzamosság két olyan kifejezés, amelyeket gyakran összekevernek azonosként, de nagyon eltérő jelentéssel bírnak.

A párhuzamosságot lényegében úgy definiálják, hogy egyidejűleg sok munkát vagy egy program különböző munkaegységeit kezeljük.

Programozási kontextusban az történik, hogy ugyanannak a programnak különböző részei a processzor különböző magjaihoz vannak hozzárendelve, amelyek mindegyik részt önállóan hajtják végre, és kommunikálnak egymással, így több munkát végeznek el egyszerre.

A párhuzamosságot viszont egyszerűen úgy definiálhatjuk

Egyszerre nagyon sok munka elvégzése ugyanazon a programon a végrehajtási idő felgyorsítása érdekében.

Programozási kontextusban ugyanannak a programnak a különböző részei párhuzamosan futnak, és az egyes részek végrehajtása egy időben történik, ezáltal felgyorsul a program végrehajtási ideje.

Multi-threading Pythonban

Pythonban a concurrent.futuresmodul segítségével érhetjük el a többszálú feldolgozás funkcionalitását. Magas szintű API-t biztosít az aszinkron feladatok elindításához. A ThreadPoolExecutorosztály felületet biztosít a szálak indításához és kezeléséhez.

import concurrent.futures
with concurrent.futures.ThreadPoolExecutor() as executor:
    executor.map(function_name, iterable)

A végrehajtó objektumot egy környezetkezelővel hozzuk létre, és a párhuzamosan végrehajtani kívánt metóduson meghívjuk a map függvényt. A leképezés függvény egy szálat hoz létre a bemeneti iteráció minden értékéhez.

Hogyan működik a többszálú Pythonban:

Bár azt mondjuk, hogy a python támogatja a többszálas működést, de ami a színfalak mögött történik, az egészen más. A pythonban minden folyamat egyetlen magon fut. Tehát amikor ugyanannak a folyamatnak több szálát hozzuk létre, mindegyik ugyanazon a magon fut, és így megosztja az erőforrásokat és a memóriaterületet. Annak megakadályozása érdekében, hogy az egyik szál módosítsa egy másik szál végrehajtási eredményeit, mivel ugyanazokat az erőforrásokat használják, a Python a „Global Interpreter Lock” koncepciót alkalmazza.

Lényegében egyszerre csak egy szál használja a megosztott memóriaterületet és erőforrásokat, és intelligens kontextusváltást végez a szálak között, így egyetlen szál sem tudja megváltoztatni a másik szál működését. Ezért a pythonban a többszálú párhuzamosítást használó párhuzamosság meglehetősen távoli kifejezés, mivel így nem érjük el a valódi párhuzamosságot.

Többszörös feldolgozás Pythonban

A Pythonban ugyanazzal a concurrent.futuresmodullal érhetjük el a többszörös feldolgozás funkcionalitását. A ProcessPoolExecutor osztály felületet biztosít több folyamat elindításához és kezeléséhez.

import concurrent.futures
with concurrent.futures.ProcessPoolExecutor() as executor:
    executor.map(function_name, iterable)

Csakúgy, mint a többszálú kezelésnél, a végrehajtó objektumot egy környezetkezelővel hozzuk létre, és a párhuzamosan végrehajtani kívánt metóduson meghívjuk a map függvényt. A térkép függvény létrehoz egy folyamatot a bemeneti iterable minden egyes értékéhez.

Hogyan működik a többszörös feldolgozás a Pythonban:

Több feldolgozás esetén minden folyamat más-más magon fut a gépen lévő magok számától függően. Ezért nincs szükség GIL-re a többszörös feldolgozás során, mivel minden folyamat független. Így a többszörös feldolgozás valójában biztosítja számunkra a tényleges párhuzamosságot a pythonban. De ez csak akkor működik, ha jól csinálják. Ha van 12 feladatunk és egy 4 magos gépünk, akkor magonként egy folyamat lenne az ideális eset, amely a kívánt valódi párhuzamosságot biztosítaná. Ha több folyamatot hozunk létre, mint ahány mag az egyes folyamatok versengenek az erőforrásokért, ez kontextusváltáshoz és így párhuzamosság helyett párhuzamossághoz vezetne.

Benchmarking többszálas és többszörös feldolgozás Pythonban

Ebben a részben megosztom azokat az eredményeket, amelyeket két különböző kísérlet elvégzésével kaptam annak meghatározására, hogy melyik párhuzamos végrehajtási módszer jobb és milyen feladatokhoz.

Általánosságban a végrehajtandó feladatokat intenzív számítási feladatokként osztályozzuk, amelyek sok számítást igényelnek a CPU-n, vagy intenzív I/O feladatokként, amelyek sok I/O műveletet tartalmaznak. például a fájlok áthelyezése a könyvtárak között vagy sok HTTP-kérés.

I/O intenzív feladat

Az alábbiakban bemutatom az I/O intenzív feladat végrehajtását.

Ez a módszer az I/O műveleteket végzi el a programban. Kapunk egy listát a képfájlnevekről, és egyenként továbbítjuk ennek a metódusnak. Csak megnyitja a fájlokat, végrehajt egy szürkeárnyalatos átalakítást, létrehoz egy miniatűrt a képről, és elmenti a feldolgozott könyvtárba.

Ezt a módszert először egyszerű soros végrehajtással, majd többszálas, majd több feldolgozással hajtjuk végre.

Intenzív számítási feladat

Az alábbiakban bemutatom a Compute intenzív feladat megvalósítását.

Ez a módszer meghívásakor a számláló változót növeli a 9⁹ tartományban lévő minden egyes értékkel.

Ismét ezt a módszert először egyszerű soros végrehajtással, majd többszálas, majd több feldolgozással hajtjuk végre. A compute_intensive_process metódus minden forgatókönyv esetén négyszer kerül meghívásra.

Összehasonlítási eredmények

A fenti módszerek végrehajtása után mind az I/O intenzív, mind a számításigényes műveleteknél a következő eredmények születtek:

Amint azt az I/O-intenzív műveleteknél láthatjuk, a soros végrehajtás a legrosszabb teljesítményt nyújtja, ezt követi a második legrosszabb a többszálú feldolgozás és a legjobb végrehajtást biztosító többszálas. Bár azt mondtuk, hogy a többszálú eljárás valójában nem valósítja meg a párhuzamosságot, de I/O műveletek esetén nem használjuk a CPU-t hatalmas számításokhoz, hanem csak elindítunk egy I/O kérést és várjuk a választ.

Miért működik rosszul a többszörös feldolgozás I/O műveletek esetén?

Ennek oka az, hogy az új folyamatok megjelenése önmagában költséges művelet, és így növeli a több feladat létrehozásának és végrehajtásának többletköltségét. De még mindig jobban teljesít, mint a soros végrehajtás.

A Compute Intensive Operations esetében azonban jól látható, hogy a többszörös feldolgozás adja a legjobb teljesítményt, és ebben a forgatókönyvben meglepő módon a soros végrehajtás követi, amely a 2. legjobb teljesítményt adja, a többszálas művelet pedig a legrosszabb teljesítményt nyújtja.

Amint azt korábban kifejtettük, az egyes folyamatok egyedi magokon futnak, így párhuzamosan vagy párhuzamosan hajtják végre.

Miért teljesít gyengébb a többszálas végrehajtás a soros végrehajtáshoz képest?

Ennek az az oka, hogy egyszerre csak egy szál kerül végrehajtásra, és a kontextus közötti váltás többletköltséggel jár, ami növeli a teljes többletköltséget, és ezáltal csökkenti az általános teljesítményt. Például. ha a soros végrehajtás 100 másodpercet vesz igénybe 5 feladat végrehajtásához, akkor a többszálú, soros módon végrehajtott végrehajtás 100 másodpercet + a környezeti többletköltséget vesz igénybe ugyanazon öt feladat végrehajtásához.

Következtetés

Amint fentebb láttuk, a többszálú és több feldolgozási műveletnek egyaránt megvannak a maga előnyei bizonyos típusú feladatok elvégzésében. A nagy I/O műveleteket igénylő feladatoknál jobb a többszálú feldolgozást, a CPU hatalmas számításait igénylő feladatoknál pedig jobb a többszálú feldolgozást.

Az erre a konkrét használati esetre vonatkozó teljes projektem megtalálható a GitHub profilomban itt.



Ha tetszik ez a cikk, kérjük, kövessen engem a médián, hogy megtekinthesse további csodálatos cikkeimet. Ez minden, köszi :).