Hỗ trợ Python cho luồng miễn phí

Bắt đầu với bản phát hành 3.13, CPython đã hỗ trợ bản dựng Python có tên free threading trong đó global interpreter lock (GIL) bị tắt. Thực thi luồng tự do cho phép tận dụng tối đa sức mạnh xử lý sẵn có bằng cách chạy các luồng song song trên các lõi CPU có sẵn. Mặc dù không phải tất cả phần mềm đều tự động được hưởng lợi từ điều này, nhưng các chương trình được thiết kế theo luồng sẽ chạy nhanh hơn trên phần cứng đa lõi.

Một số gói của bên thứ ba, đặc biệt là các gói có extension module, có thể chưa sẵn sàng để sử dụng trong bản dựng luồng tự do và sẽ kích hoạt lại GIL.

Tài liệu này mô tả ý nghĩa của việc phân luồng tự do cho mã Python. Xem Hỗ trợ tiện ích mở rộng C API để phân luồng miễn phí để biết thông tin về cách viết phần mở rộng C hỗ trợ bản dựng luồng tự do.

Xem thêm

PEP 703 – Tùy chọn Khóa trình thông dịch toàn cầu trong CPython để có mô tả tổng thể về Python có luồng tự do.

Cài đặt

Bắt đầu với Python 3.13, trình cài đặt macOS và Windows chính thức hỗ trợ tùy chọn cài đặt các tệp nhị phân Python có luồng miễn phí. Các trình cài đặt có sẵn tại https://www.python.org/downloads/.

Để biết thông tin về các nền tảng khác, hãy xem Installing a Free-Threaded Python, hướng dẫn cài đặt do cộng đồng duy trì để cài đặt Python có luồng miễn phí.

Khi xây dựng CPython từ nguồn, nên sử dụng tùy chọn cấu hình --disable-gil để xây dựng trình thông dịch Python có luồng tự do.

Xác định Python có luồng tự do

Để kiểm tra xem trình thông dịch hiện tại có hỗ trợ phân luồng tự do hay không, python -VVsys.version có chứa "bản dựng phân luồng tự do". Chức năng sys._is_gil_enabled() mới có thể được sử dụng để kiểm tra xem GIL có thực sự bị vô hiệu hóa trong quá trình chạy hay không.

Biến cấu hình sysconfig.get_config_var("Py_GIL_DISABLED") có thể được sử dụng để xác định xem bản dựng có hỗ trợ phân luồng miễn phí hay không. Nếu biến được đặt thành 1 thì bản dựng sẽ hỗ trợ phân luồng miễn phí. Đây là cơ chế được đề xuất cho các quyết định liên quan đến cấu hình bản dựng.

Khóa trình thông dịch toàn cầu trong Python có luồng tự do

Các bản dựng CPython luồng tự do hỗ trợ tùy chọn chạy với GIL được bật trong thời gian chạy bằng cách sử dụng biến môi trường PYTHON_GIL hoặc tùy chọn dòng lệnh -X gil.

GIL cũng có thể được bật tự động khi nhập mô-đun mở rộng C-API không được đánh dấu rõ ràng là hỗ trợ tạo luồng tự do. Một cảnh báo sẽ được in trong trường hợp này.

Ngoài tài liệu về gói riêng lẻ, các trang web sau còn theo dõi trạng thái của các gói phổ biến hỗ trợ phân luồng miễn phí:

An toàn chủ đề

Bản dựng CPython theo luồng miễn phí nhằm mục đích cung cấp hành vi an toàn luồng tương tự ở cấp độ Python cho bản dựng hỗ trợ GIL mặc định. Các loại tích hợp như dict, listset sử dụng khóa bên trong để bảo vệ khỏi các sửa đổi đồng thời theo cách hoạt động tương tự như GIL. Tuy nhiên, Python trước đây không đảm bảo hành vi cụ thể cho các sửa đổi đồng thời đối với các loại dựng sẵn này, do đó, điều này phải được coi là mô tả về cách triển khai hiện tại chứ không phải là sự đảm bảo cho hành vi hiện tại hoặc tương lai.

Ghi chú

Bạn nên sử dụng threading.Lock hoặc các nguyên tắc đồng bộ hóa cơ bản khác thay vì dựa vào các khóa bên trong của các loại tích hợp sẵn, khi có thể.

Những hạn chế đã biết

Phần này mô tả các hạn chế đã biết của bản dựng CPython luồng tự do.

bất tử

Trong bản dựng luồng tự do, một số đối tượng là immortal. Các đối tượng bất tử không bị hủy phân bổ và có số lượng tham chiếu không bao giờ được sửa đổi. Điều này được thực hiện để tránh tranh chấp về số lượng tham chiếu có thể ngăn cản việc mở rộng quy mô đa luồng hiệu quả.

Kể từ bản phát hành 3.14, khả năng bất tử bị giới hạn ở:

  • Các hằng mã: hằng số, chuỗi ký tự dạng chuỗi và ký tự tuple được tạo thành từ các hằng số khác.

  • Chuỗi được thực hiện bởi sys.intern().

Đóng khung đồ vật

Sẽ không an toàn khi truy cập frame.f_locals từ đối tượng frame nếu khung đó hiện đang thực thi trong một luồng khác và làm như vậy có thể làm hỏng trình thông dịch.

Trình vòng lặp

Nói chung, việc truy cập cùng một đối tượng iterator từ nhiều luồng đồng thời là không an toàn và các luồng có thể thấy các phần tử trùng lặp hoặc bị thiếu.

Hiệu suất đơn luồng

Bản dựng theo luồng miễn phí có thêm chi phí khi thực thi mã Python so với bản dựng hỗ trợ GIL mặc định. Số lượng chi phí phụ thuộc vào khối lượng công việc và phần cứng. Trên bộ điểm chuẩn pyperformance, chi phí trung bình dao động từ khoảng 1% trên macOS aarch64 đến 8% trên hệ thống Linux x86-64.

Thay đổi hành vi

Phần này mô tả các thay đổi về hành vi của CPython với bản dựng luồng tự do.

Biến bối cảnh

Trong bản dựng luồng tự do, cờ thread_inherit_context được đặt thành true theo mặc định, điều này khiến các luồng được tạo bằng threading.Thread bắt đầu bằng bản sao Context() của người gọi start(). Trong bản dựng mặc định hỗ trợ GIL, cờ mặc định là sai nên các luồng bắt đầu bằng Context() trống.

Bộ lọc cảnh báo

Trong bản dựng luồng tự do, cờ context_aware_warnings được đặt thành true theo mặc định. Trong bản dựng mặc định hỗ trợ GIL, cờ mặc định là sai. Nếu cờ đúng thì trình quản lý ngữ cảnh warnings.catch_warnings sẽ sử dụng biến ngữ cảnh cho các bộ lọc cảnh báo. Nếu cờ sai thì catch_warnings sẽ sửa đổi danh sách bộ lọc chung, danh sách này không an toàn cho luồng. Xem mô-đun warnings để biết thêm chi tiết.