Xử lý song song python

Trong hướng dẫn này, bạn sẽ khám phá mối quan hệ giữa mô-đun đa xử lý cho đồng thời dựa trên quy trình và Khóa thông dịch viên toàn cầu trong Python

Bắt đầu nào

Mục lục

  • Đa xử lý có bị giới hạn bởi GIL không?
  • Khóa phiên dịch toàn cầu là gì?
  • Đa xử lý và Khóa phiên dịch toàn cầu
  • Đọc thêm
  • mang đi

Đa xử lý có bị giới hạn bởi GIL không?

Mô-đun “đa xử lý” cung cấp đồng thời dựa trên quy trình trong Python

Một quy trình đề cập đến một chương trình máy tính

Mỗi chương trình Python là một quá trình và có một luồng mặc định được gọi là luồng chính được sử dụng để thực hiện các hướng dẫn chương trình của bạn. Trên thực tế, mỗi quy trình là một phiên bản của trình thông dịch Python thực thi các lệnh Python (mã byte Python), cấp độ này thấp hơn một chút so với mã bạn nhập vào chương trình Python của mình

Trung tâm của mô-đun đa xử lý là đa xử lý. Lớp quy trình cung cấp trình xử lý Python trên quy trình gốc (được quản lý bởi hệ điều hành bên dưới)

Đôi khi chúng ta có thể cần tạo các tiến trình con mới trong chương trình của mình để thực thi mã đồng thời

Python cung cấp khả năng tạo và quản lý các quy trình mới thông qua cơ chế đa xử lý. lớp quy trình

Sau khi liên quan đến mô-đun đa xử lý và tạo các tiến trình con thông qua mô-đun đa xử lý. Lớp quy trình là liệu chúng có bị ảnh hưởng bởi Khóa phiên dịch toàn cầu (GIL) hay không

Nếu các quy trình con bị ảnh hưởng bởi GIL, nó sẽ giới hạn các loại tác vụ mà chúng có thể thực thi song song với các loại tác vụ giải phóng GIL, chẳng hạn như chặn I/O

Mặt khác, nếu các tiến trình con không bị ảnh hưởng bởi GIL, thì các worker có thể thực thi các tác vụ tùy ý bằng cách sử dụng song song hoàn toàn

Là mô-đun đa xử lý và đa xử lý. Lớp quy trình phải tuân theo GIL?

Chạy các vòng lặp của bạn bằng cách sử dụng tất cả các CPU, tải xuống cuốn sách MIỄN PHÍ của tôi để tìm hiểu cách thực hiện

Khóa phiên dịch toàn cầu là gì?

Phần bên trong của trình thông dịch Python không an toàn cho luồng

Điều này có nghĩa là có thể có các điều kiện tương tranh giữa nhiều luồng trong một quy trình Python, có khả năng dẫn đến hành vi không mong muốn và dữ liệu bị hỏng

Như vậy, trình thông dịch Python sử dụng Khóa thông dịch viên toàn cầu, viết tắt là GIL, để thực hiện các lệnh được thực thi bởi trình thông dịch Python (được gọi là mã byte Python) an toàn theo luồng

GIL là một mẫu lập trình trong trình thông dịch Python tham chiếu được gọi là CPython, mặc dù các khóa tương tự tồn tại trong các ngôn ngữ thông dịch khác, chẳng hạn như Ruby. Nó là một khóa theo nghĩa là nó sử dụng một nguyên hàm đồng bộ hóa được gọi là loại trừ lẫn nhau hoặc khóa mutex để đảm bảo rằng chỉ một luồng thực thi có thể thực thi các lệnh tại một thời điểm trong quy trình Python

Trong CPython, khóa trình thông dịch toàn cầu, hoặc GIL, là một mutex bảo vệ quyền truy cập vào các đối tượng Python, ngăn nhiều luồng thực thi mã byte Python cùng một lúc. GIL ngăn chặn các điều kiện chủng tộc và đảm bảo an toàn cho luồng

— Khóa phiên dịch toàn cầu, Python Wiki

Tác dụng của GIL là bất cứ khi nào một luồng trong chương trình Python muốn chạy, nó phải có khóa trước khi thực thi. Đây không phải là vấn đề đối với hầu hết các chương trình Python có một luồng thực thi duy nhất, được gọi là luồng chính

Nó có thể trở thành một vấn đề trong các chương trình Python đa luồng, chẳng hạn như các chương trình sử dụng luồng. Lớp chủ đề hoặc đồng thời. tương lai. Lớp ThreadPoolExecutor

Khóa được giải phóng rõ ràng và được mua lại định kỳ bởi mỗi luồng Python, cụ thể là sau khoảng 100 lệnh mã byte được thực thi trong trình thông dịch. Điều này cho phép các luồng khác trong quy trình Python chạy, nếu có

Khóa cũng được giải phóng trong một số trường hợp, cho phép các luồng khác chạy

Một ví dụ quan trọng là khi một luồng thực hiện thao tác I/O, chẳng hạn như đọc hoặc ghi từ tài nguyên bên ngoài như tệp, ổ cắm hoặc thiết bị

May mắn thay, nhiều hoạt động có khả năng bị chặn hoặc chạy lâu, chẳng hạn như I/O, xử lý hình ảnh và xử lý số NumPy, xảy ra bên ngoài GIL. Do đó, chỉ trong các chương trình đa luồng dành nhiều thời gian bên trong GIL, diễn giải mã byte CPython, GIL mới trở thành nút cổ chai

— Khóa phiên dịch toàn cầu, Python Wiki

Khóa cũng được phát hành rõ ràng bởi một số thư viện Python của bên thứ ba khi thực hiện các hoạt động tính toán tốn kém trong mã C, chẳng hạn như nhiều hoạt động mảng trong NumPy

Trong CPython, do Khóa phiên dịch toàn cầu, chỉ một luồng có thể thực thi mã Python cùng một lúc (mặc dù một số thư viện định hướng hiệu suất nhất định có thể khắc phục giới hạn này)

— phân luồng — Song song dựa trên luồng

GIL là một giải pháp đơn giản và hiệu quả để đảm bảo an toàn luồng trong trình thông dịch Python, nhưng nó có nhược điểm chính là đa luồng hoàn toàn không được hỗ trợ bởi Python

Một giải pháp thay thế có thể là làm cho trình thông dịch trở nên an toàn theo luồng một cách rõ ràng bằng cách bảo vệ từng phần quan trọng. Điều này đã được thử nhiều lần và thường dẫn đến hiệu suất kém hơn tới 30% cho các chương trình Python đơn luồng

Thật không may, cả hai thử nghiệm đều cho thấy hiệu suất đơn luồng giảm mạnh (chậm hơn ít nhất 30%), do lượng khóa chi tiết cần thiết để bù đắp cho việc loại bỏ GIL

— Khóa phiên dịch toàn cầu Python, Python Wiki

Bây giờ chúng ta đã quen thuộc với GIL, hãy xem cách đa xử lý bị ảnh hưởng

Bối rối với API mô-đun đa xử lý?
Tải xuống bảng cheat PDF MIỄN PHÍ của tôi

Đa xử lý và Khóa phiên dịch toàn cầu

Mô-đun đa xử lý cung cấp đồng thời dựa trên quy trình không bị giới hạn bởi Khóa phiên dịch toàn cầu

Cả luồng và quy trình đều có thể thực thi đồng thời (không theo thứ tự), nhưng chỉ các quy trình python mới có thể thực thi song song (đồng thời), không phải luồng Python (với một số lưu ý)

Điều này có nghĩa là nếu chúng ta muốn mã Python chạy trên tất cả các lõi CPU và tận dụng tốt nhất phần cứng hệ thống của mình, chúng ta nên sử dụng đồng thời dựa trên quy trình

Gói đa xử lý cung cấp cả đồng thời cục bộ và từ xa, hỗ trợ hiệu quả Khóa thông dịch viên toàn cầu bằng cách sử dụng các quy trình con thay vì các luồng. Do đó, mô-đun đa xử lý cho phép lập trình viên tận dụng tối đa nhiều bộ xử lý trên một máy nhất định. Nó chạy trên cả Unix và Windows

— đa xử lý — Song song dựa trên quy trình

Trên thực tế, Jesse Noller và Richard Oudkerk đã đề xuất và phát triển mô-đun đa xử lý (ban đầu được gọi là “pyprocessing”) bằng Python để khắc phục những hạn chế và hỗ trợ GIL

Gói pyprocessing cung cấp một phương pháp để hỗ trợ GIL, cho phép các ứng dụng trong CPython tận dụng lợi thế của kiến ​​trúc đa lõi mà không yêu cầu người dùng thay đổi hoàn toàn mô hình lập trình của họ (i. e. bỏ lập trình luồng cho một cách tiếp cận “đồng thời” khác - Twisted, Actors, v.v.)

— PEP 371 – Bổ sung gói đa xử lý vào thư viện chuẩn

Mô-đun đa xử lý không bị giới hạn bởi Khóa phiên dịch toàn cầu và có thể đạt được tính song song hoàn toàn trong Python


Khóa học đa xử lý Python miễn phí

Tải xuống bảng cheat API đa xử lý của tôi và như một phần thưởng, bạn sẽ nhận được quyền truy cập MIỄN PHÍ vào khóa học email 7 ngày của tôi

Khám phá cách sử dụng mô-đun đa xử lý Python, bao gồm cách tạo và bắt đầu các tiến trình con cũng như cách sử dụng khóa mutex và semaphores