Rumah > pembangunan bahagian belakang > Tutorial Python > Python Gerbang kepada Multithreading Berprestasi Tinggi Tanpa GIL

Python Gerbang kepada Multithreading Berprestasi Tinggi Tanpa GIL

Mary-Kate Olsen
Lepaskan: 2025-01-06 16:58:41
asal
682 orang telah melayarinya

pengenalan

Python telah lama dikenali kerana kemudahan penggunaan dan serba boleh, tetapi satu topik yang telah mencetuskan banyak perbincangan dalam komuniti Python ialah Global Interpreter Lock (GIL). GIL telah menjadi pelindung dan halangan untuk model konkurensi Python, terutamanya untuk tugas terikat CPU yang sebaliknya boleh mengambil kesempatan daripada berbilang teras CPU. Walau bagaimanapun, dengan keluaran Python 3.13, pembangun Python mempunyai pilihan baharu yang hebat: keupayaan untuk melumpuhkan GIL. Blog ini akan meneroka apa itu GIL, mengapa ia menjadi penghalang untuk prestasi dalam multithreading, dan cara untuk mengesan dan melumpuhkan GIL dalam Python 3.13 untuk membuka kunci prestasi multithreading yang sebenar.

Apakah itu Global Interpreter Lock (GIL)

Global Interpreter Lock (GIL) ialah mutex yang melindungi akses kepada objek Python, menghalang berbilang benang asli daripada melaksanakan kod bait Python sekaligus. Ini memastikan keselamatan benang untuk program Python tetapi dengan kos pelaksanaan serentak. GIL menjadikan benang Python lebih cekap untuk tugas terikat I/O tetapi mengehadkan prestasinya untuk tugas terikat CPU.

Mengapa GIL adalah Bottleneck untuk Multithreading

GIL Python membenarkan hanya satu utas untuk dilaksanakan secara serentak, walaupun dalam program berbilang benang. Walaupun ini baik untuk tugas terikat I/O di mana program sedang menunggu operasi input/output, ia sangat mengehadkan prestasi untuk tugas terikat CPU seperti pecah nombor, analisis data atau pemprosesan imej.

Python 3.13: Membuka Kunci Multithreading dengan GIL Dilumpuhkan

Dengan Python 3.13, pembangun mempunyai pilihan untuk melumpuhkan GIL semasa proses binaan Python. Walau bagaimanapun, melumpuhkan GIL tidak tersedia dalam pengedaran Python pra-bina. Sebaliknya, anda mesti menyusun Python 3.13 daripada sumber dengan pilihan --disable-gil.

Pilihan baharu ini membuka pintu untuk keselarian sebenar dalam tugas berbilang benang terikat CPU, membenarkan urutan dilaksanakan secara selari merentas berbilang teras.

Prasyarat untuk Menggunakan Python 3.13 Tanpa GIL

  • Kod Sumber Python 3.13: Melumpuhkan GIL tidak tersedia dalam binari standard pra-bina. Anda mesti membina Python 3.13 daripada sumber dengan bendera --disable-gil.
  • CPU Berbilang Teras: Anda memerlukan CPU berbilang teras untuk mendapat manfaat daripada berbilang benang sebenar, kerana kini benang akan berjalan selari merentas berbilang teras.

Menyusun Python 3.13 dengan GIL Disabled

Untuk melumpuhkan GIL menggunakan bendera -X gil=0, anda perlu menyusun Python daripada sumber dengan bendera --disable-gil didayakan. Begini caranya

Langkah demi Langkah

  • Muat turun Kod Sumber Python 3.13 Anda perlu memuat turun kod sumber Python 3.13 tarball daripada laman web rasmi Python. Ini kerana binari pra-bina (seperti yang anda muat turun terus dari python.org) tidak disusun dengan sokongan untuk melumpuhkan GIL. Anda boleh memuat turunnya menggunakan pelayar web atau menggunakan wget atau bahkan menggunakan curl di terminal anda
wget https://www.python.org/ftp/python/3.13.0/Python-3.13.0.tgz
Salin selepas log masuk
  • Ekstrak Sumber:
tar -xf Python-3.13.0.tgz
cd Python-3.13.0
Salin selepas log masuk
  • Konfigurasikan binaan dengan --disable-gil Anda perlu mengkonfigurasi Python dengan --disable-gil untuk menyokong pilihan untuk melumpuhkan GIL.
./configure --disable-gil
Salin selepas log masuk
  • Kompil dan pasang Python:
make
sudo make altinstall 
Salin selepas log masuk
  • Jika langkah altinstall gagal, kemudian jalankan semula Perintah konfigurasi dengan --prefix
./configure --disable-gil --prefix=$HOME/python3.13
Salin selepas log masuk
  • Jalankan make altinstall dalam Direktori Ditentukan Kemudian, jalankan arahan make altinstall
make altinstall
Salin selepas log masuk

Bagaimana untuk Mengesan GIL dalam Python 3.13

Dalam Python 3.13, anda boleh menyemak sama ada GIL didayakan atau dilumpuhkan menggunakan fungsi sys._is_gil_enabled().

import sys

def check_gil_status():
    if sys.version_info >= (3, 13):
        status = sys._is_gil_enabled()
        if status:
            print("GIL is currently enabled.")
        else:
            print("GIL is currently disabled.")
    else:
        print("Python version does not support GIL status detection.")

check_gil_status()
Salin selepas log masuk

Hands-On: Python Multithreading dengan GIL vs GIL-Free

Kod Python berikut telah dibangunkan untuk menilai keuntungan prestasi apabila melumpuhkan GIL dalam Python 3.13. Skrip melaksanakan lapan utas serentak, setiap satu ditugaskan untuk mengira faktor perdana nombor besar. Dengan memanfaatkan keselarian sebenar, kod tersebut menyerlahkan prestasi dipertingkat yang dicapai tanpa GIL.

#!/usr/bin/env python3
import sys
import sysconfig
import time
from threading import Thread
from multiprocessing import Process


# Decorator to measure execution time of functions
def calculate_execution_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        execution_time = end_time - start_time
        print(f"{func.__name__} took {execution_time:.4f} seconds.")
        return result

    return wrapper


# Compute-intensive task: Iterative Fibonacci calculation
def compute_fibonacci(n):
    """Compute Fibonacci number for a given n iteratively."""
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a


# Single-threaded task execution
@calculate_execution_time
def run_single_threaded(nums):
    for num in nums:
        compute_fibonacci(num)


# Multi-threaded task execution
@calculate_execution_time
def run_multi_threaded(nums):
    threads = [Thread(target=compute_fibonacci, args=(num,)) for num in nums]
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()


# Multi-processing task execution
@calculate_execution_time
def run_multi_processing(nums):
    processes = [Process(target=compute_fibonacci, args=(num,)) for num in nums]
    for process in processes:
        process.start()
    for process in processes:
        process.join()


# Main execution function
def main():
    # Check Python version and GIL status for Python 3.13+
    print(f"Python Version: {sys.version}")

    py_version = float(".".join(sys.version.split()[0].split(".")[:2]))
    status = sysconfig.get_config_var("Py_GIL_DISABLED")

    if py_version >= 3.13:
        status = sys._is_gil_enabled()

    if status is None:
        print("GIL cannot be disabled for Python <= 3.12")
    elif status == 0:
        print("GIL is currently disabled")
    elif status == 1:
        print("GIL is currently active")

    # Run tasks on the same input size for comparison
    nums = [300000] * 8

    print("\nRunning Single-Threaded Task:")
    run_single_threaded(nums)

    print("\nRunning Multi-Threaded Task:")
    run_multi_threaded(nums)

    print("\nRunning Multi-Processing Task:")
    run_multi_processing(nums)


if __name__ == "__main__":
    main()

Salin selepas log masuk

Analisis:

## Python 3.13 with GIL Disabled
Python Version: 3.13.0 experimental free-threading build (main, Oct 14 2024, 17:09:28) [Clang 14.0.0 (clang-1400.0.29.202)]
GIL is currently disabled

Running Single-Threaded Task:
run_single_threaded took 8.6587 seconds.

Running Multi-Threaded Task:
run_multi_threaded took 1.3885 seconds.

Running Multi-Processing Task:
run_multi_processing took 1.5953 seconds.

## Python 3.13 with GIL Enabled
Python Version: 3.13.0 experimental free-threading build (main, Oct 14 2024, 17:09:28) [Clang 14.0.0 (clang-1400.0.29.202)]
GIL is currently active

Running Single-Threaded Task:
run_single_threaded took 8.7108 seconds.

Running Multi-Threaded Task:
run_multi_threaded took 8.6645 seconds.

Running Multi-Processing Task:
run_multi_processing took 1.4530 seconds.

## Python 3.12 
Python Version: 3.12.6 (main, Sep  7 2024, 19:30:10) [Clang 14.0.0 (clang-1400.0.29.202)]
GIL cannot be disabled for Python <= 3.12

Running Single-Threaded Task:
run_single_threaded took 8.7004 seconds.

Running Multi-Threaded Task:
run_multi_threaded took 8.6297 seconds.

Running Multi-Processing Task:
run_multi_processing took 1.4876 seconds.
Salin selepas log masuk

Prestasi berbilang benang: Faedah sebenar melumpuhkan GIL terbukti dalam senario berbilang benang:

Dengan GIL dilumpuhkan (3.13), masa pelaksanaan ialah 1.5703 saat.
Dengan GIL didayakan (3.13), masa pelaksanaan ialah 8.5901 saat.
Keputusan: Tindakan melumpuhkan GIL menghasilkan peningkatan prestasi kira-kira 81.7% untuk tugasan berbilang benang.

Python The Gateway to High-Performance Multithreading Without GIL

Python The Gateway to High-Performance Multithreading Without GIL

Carta jelas menunjukkan bahawa melumpuhkan GIL dalam Python 3.13 membawa kepada peningkatan prestasi yang ketara untuk tugasan terikat CPU berbilang benang, membolehkan Python menggunakan berbilang teras CPU secara selari dengan cekap. Walaupun prestasi satu-benang dan berbilang pemprosesan sebahagian besarnya kekal tidak terjejas, prestasi berbilang-benang menunjukkan peningkatan yang ketara, menjadikan Python 3.13 sebagai penukar permainan untuk aplikasi intensif CPU yang bergantung pada berbilang-benang.

Walau bagaimanapun, versi Python sebelum 3.13 tidak menyokong pelumpuhan GIL, yang menjelaskan mengapa prestasi berbilang benang mereka kekal serupa dengan Python 3.13 dengan GIL didayakan. Had ini dalam versi terdahulu terus menyekat keupayaan Python untuk mengeksploitasi sepenuhnya berbilang benang untuk tugas terikat CPU.

Pertimbangan Utama Sebelum Melumpuhkan GIL

Melumpuhkan Global Interpreter Lock (GIL) dalam Python 3.13 boleh membuka kunci peningkatan prestasi yang ketara dalam tugasan terikat CPU berbilang benang. Walau bagaimanapun, terdapat beberapa faktor penting yang perlu dipertimbangkan sebelum berbuat demikian:

  • Keselamatan Benang: Tanpa GIL, anda mesti mengendalikan keselamatan benang secara manual menggunakan kunci atau mekanisme penyegerakan lain untuk mengelakkan keadaan perlumbaan dalam kod anda.

  • Potensi Kemerosotan Prestasi: Penguncian berbutir halus boleh menimbulkan perbalahan, yang mungkin merendahkan prestasi dalam tugasan berbenang tunggal atau terikat I/O yang sebelum ini mendapat manfaat daripada GIL.

  • Keserasian dengan Perpustakaan Pihak Ketiga: Banyak sambungan dan perpustakaan C menganggap kehadiran GIL untuk keselamatan benang. Melumpuhkan GIL mungkin memerlukan kemas kini pada perpustakaan ini untuk memastikan ia berfungsi dengan betul dalam persekitaran berbilang benang.

  • Pengurusan Memori Kompleks: Melumpuhkan GIL memperkenalkan lebih banyak kerumitan dalam pengurusan memori, memerlukan pengendalian memori selamat benang yang boleh meningkatkan risiko pepijat dan ralat.

  • Tugas terikat I/O: Melumpuhkan GIL memberikan faedah terhad untuk tugas terikat I/O, di mana mekanisme I/O tidak menyekat seperti asyncio mungkin lebih berkesan.

  • Kesukaran dalam Menyahpepijat: Tanpa GIL, penyahpepijatan aplikasi berbilang benang boleh menjadi lebih mencabar disebabkan peningkatan kemungkinan keadaan perlumbaan dan kebuntuan.

  • Penggunaan Memori Lebih Tinggi: Menggunakan kunci dan mengurus keadaan benang tanpa GIL boleh meningkatkan penggunaan memori, terutamanya dalam aplikasi berbilang benang.

  • Sistem Terbenam: Melumpuhkan GIL mungkin merumitkan penyepaduan Python dengan persekitaran berbilang benang dalam sistem terbenam, memerlukan lebih banyak usaha untuk penyepaduan yang berkesan.

  • Lock Contention: Dalam sesetengah kes, melumpuhkan GIL boleh membawa kepada mengunci pertikaian antara thread, yang mungkin mengurangkan peningkatan prestasi yang dijangkakan.

Repositori GitHub

Anda boleh mendapatkan kod sumber lengkap untuk contoh dalam blog ini di GitHub saya:

Analisis Prestasi Python GIL

Penafian:

Ini adalah blog peribadi. Pandangan dan pendapat yang dinyatakan di sini hanyalah pendapat pengarang dan tidak mewakili mana-mana organisasi atau mana-mana individu yang mungkin dikaitkan dengan pengarang, secara profesional atau peribadi.

Atas ialah kandungan terperinci Python Gerbang kepada Multithreading Berprestasi Tinggi Tanpa GIL. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan