CodeGym /Kurse /Python SELF DE /Umgehung des GIL

Umgehung des GIL

Python SELF DE
Level 26 , Lektion 4
Verfügbar

11.1 Global Interpreter Lock

Global Interpreter Lock (GIL) — das ist ein Mechanismus im CPython-Interpreter, der sicherstellt, dass nur ein Thread den Python-Bytecode zu einem gegebenen Zeitpunkt ausführt. GIL verhindert die parallele Ausführung von Threads, was die Leistung von Multithreading-Programmen negativ beeinflussen kann, insbesondere auf Mehrkernprozessoren.

Gründe für die Existenz von GIL

Vereinfachung der Speicherverwaltung: GIL vereinfacht die Speicherverwaltung und die Garbage Collection, wodurch Python einfacher zu implementieren ist.

Thread-Sicherheit: GIL verhindert Race Conditions, wodurch die Codeausführung ohne die Notwendigkeit von Sperrungen thread-sicher wird.

Probleme, die durch GIL verursacht werden

Begrenzte Leistung: Multithreading- Programme, die rechenintensive Aufgaben ausführen, können die Vorteile von Mehrkernprozessoren aufgrund der Einschränkungen von GIL nicht vollständig nutzen.

Verzerrte Leistung: Programme, die Threads intensiv nutzen, um Aufgaben auszuführen, können eine Leistungseinbuße aufgrund des Kontextwechsels zwischen Threads erleben.

Derzeit gibt es vier Hauptmethoden zur „Umgehung des GIL“:

11.2 Nutzung von Multi-Processing (multiprocessing)

Das Modul multiprocessing ermöglicht die Erstellung von Prozessen, die parallel ausgeführt werden und nicht durch GIL eingeschränkt sind, da jeder Prozess seinen eigenen Python-Interpreter und Speicher hat.

Beispiel:


import multiprocessing

def worker(num):
    print(f'Worker: {num}')
            
def main():
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        processes.append(p)
        p.start()
            
    for p in processes:
        p.join()
            
main()

11.3 Asynchrones Programmieren

Asynchrones Programmieren mit asyncio erlaubt die parallele Ausführung von Aufgaben, ohne den Haupt-Thread zu blockieren. Obwohl dies nicht direkt GIL umgeht, ermöglicht es die effektive Nutzung von Wartezeiten zur Ausführung anderer Aufgaben.

Beispiel:


import asyncio

async def main():
    await asyncio.sleep(1)
    print('Hallo')
            
asyncio.run(main())

11.4 Verwendung von Bibliotheken mit eigenem Thread-Management

Einige Bibliotheken, wie NumPy und SciPy, sind in C geschrieben und verwenden eigene Mechanismen zur Thread-Verwaltung, was es ihnen ermöglicht, GIL zu umgehen und Mehrkernprozessoren für Berechnungen effizient zu nutzen.

Tatsächlich ist dies einer der Hauptgründe für den Erfolg von Python, wie langsam es auch sein mag. Alle komplexen Berechnungen sind in C/C++ neu geschrieben und werden auf allen Prozessorkernen oder sogar direkt auf den Kernen der Grafikkarte ausgeführt. Und auf modernen Grafikkarten gibt es tausende von Kernen.

Es stellt sich heraus, dass es nicht mehr wichtig ist, wie schnell oder langsam die Sprache ist, wenn alle ressourcenintensiven Berechnungen von externen Bibliotheken ausgeführt oder sogar in entfernte Rechenzentren verlagert werden.

11.5 Ausführung von Berechnungen außerhalb des Python-Interpreters

Nutzung von Erweiterungen in C/C++ oder anderen Sprachen, die Berechnungen außerhalb des Python-Interpreters ausführen können und dann das Ergebnis zurückgeben. Dies ermöglicht das Vermeiden der GIL-Blockierung während der Ausführung von intensiven Berechnungen.

Beispiel für die Nutzung von Cython:


# example.pyx

def compute(int n):
    cdef int i, result = 0
    for i in range(n):
        result += i
    return result

Kompilierung und Nutzung:


cythonize -i example.pyx

import example
print(example.compute(1000000))
1
Umfrage/Quiz
Asynchronität, Level 26, Lektion 4
Nicht verfügbar
Asynchronität
Asynchronität
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION