Hướng dẫn can you multi thread in python? - bạn có thể đa luồng trong python không?

Gil không ngăn chặn luồng. Tất cả các Gil làm là đảm bảo chỉ có một luồng thực thi mã Python tại một thời điểm; Kiểm soát vẫn chuyển đổi giữa các luồng.

Những gì Gil ngăn chặn sau đó, đang sử dụng nhiều hơn một lõi CPU hoặc CPU riêng biệt để chạy các luồng song song.

Điều này chỉ áp dụng cho mã Python. Các tiện ích mở rộng C có thể và thực hiện việc giải phóng GIL để cho phép nhiều luồng mã C và một luồng python chạy qua nhiều lõi. Điều này mở rộng cho I/O được kiểm soát bởi kernel, chẳng hạn như các cuộc gọi select() cho các lần đọc và ghi ổ cắm, làm cho Python xử lý các sự kiện mạng hiệu quả một cách hợp lý trong một thiết lập đa lõi đa luồng.

Những gì nhiều triển khai máy chủ sau đó làm, được chạy nhiều hơn một quy trình Python, để cho HĐH xử lý lịch trình giữa các quy trình để sử dụng lõi CPU của bạn cho MAX. Bạn cũng có thể sử dụng thư viện multiprocessing để xử lý xử lý song song trên nhiều quy trình từ một quy trình CodeBase và Parent, nếu điều đó phù hợp với các trường hợp sử dụng của bạn.

Lưu ý rằng GIL chỉ áp dụng cho việc triển khai CPython; Jython và Ironpython sử dụng một triển khai luồng khác (các luồng thời gian chạy phổ biến Java VM và .NET tương ứng).

Để giải quyết trực tiếp bản cập nhật của bạn: Bất kỳ nhiệm vụ nào cố gắng tăng tốc độ từ thực thi song song, sử dụng mã python thuần túy, sẽ không thấy tăng tốc vì mã python có luồng bị khóa vào một luồng thực hiện tại một thời điểm. Tuy nhiên, nếu bạn trộn trong các tiện ích mở rộng C và I/O (chẳng hạn như các hoạt động PIL hoặc NUMPY) và bất kỳ mã C nào cũng có thể chạy song song với một luồng python hoạt động.

Python Threading là tuyệt vời để tạo GUI đáp ứng hoặc để xử lý nhiều yêu cầu web ngắn trong đó I/O là nút tắc nghẽn nhiều hơn mã Python. Nó không phù hợp để song song hóa mã python chuyên sâu về mặt tính toán, hãy gắn bó với mô -đun multiprocessing cho các nhiệm vụ đó hoặc đại biểu cho một thư viện bên ngoài chuyên dụng.

Một cuộc lặn sâu vào đa luồng và đa xử lý với Python và cách chúng liên quan đến sự đồng thời và song song

Ảnh của Osman Rana trên unplash

Giới thiệu

Chủ đề và đa xử lý là hai trong số các khái niệm cơ bản nhất trong lập trình. Nếu bạn đã mã hóa trong một thời gian, bạn nên bắt gặp các trường hợp sử dụng nơi bạn muốn tăng tốc các hoạt động cụ thể trong một số phần của mã của bạn. Python hỗ trợ các cơ chế khác nhau cho phép các nhiệm vụ khác nhau được thực hiện tại (gần như) cùng một lúc.

Trong hướng dẫn này, chúng tôi sẽ hiểu được sự hiểu biết về đa luồng và đa xử lý và xem trong thực tế làm thế nào các kỹ thuật này có thể được thực hiện trong Python. Chúng tôi cũng sẽ thảo luận về việc sử dụng kỹ thuật nào dựa trên việc ứng dụng có bị ràng buộc I/O hay CPU hay không.multi-threading and multi-processing and see in practise how these techniques can be implemented in Python. We’ll also discuss about which technique to use based on whether the application is I/O or CPU bound.

Trước khi thảo luận về việc xâu chuỗi và đa xử lý, nó rất quan trọng để hiểu hai thuật ngữ thường được sử dụng thay thế cho nhau. Đồng thời và song song có liên quan chặt chẽ nhưng các khái niệm khác biệt.Concurrency and parallelism are closely related but distinct concepts.

Đồng thời và song song

Trong nhiều trường hợp, chúng tôi có thể cần tăng tốc một vài hoạt động trong cơ sở mã của chúng tôi để tăng hiệu suất thực hiện. Điều này thường có thể đạt được bằng cách thực hiện nhiều nhiệm vụ song song hoặc đồng thời (nghĩa là bằng cách xen kẽ giữa nhiều nhiệm vụ). Việc bạn có thể tận dụng sự đồng thời hay song song thực sự phụ thuộc vào mã của bạn nhưng trên máy cũng đang chạy nó.

Trong thực thi đồng thời, hai hoặc nhiều nhiệm vụ có thể bắt đầu, thực thi và hoàn thành trong các khoảng thời gian chồng chéo. Do đó, những nhiệm vụ này không nhất thiết phải chạy đồng thời - chúng chỉ cần tiến bộ theo cách chồng chéo. concurrent execution, two or more tasks can start, execute and complete in overlapping time periods. Therefore, these tasks don’t necessarily have to run simultaneously — they just need to make progress in an overlapping manner.

Đồng thời: Một điều kiện tồn tại khi ít nhất hai luồng đang tiến bộ. Một hình thức song song tổng quát hơn có thể bao gồm việc cắt thời gian như một hình thức song song ảo.

- Hướng dẫn lập trình đa luồng của Sun Sun

Bây giờ, hãy để xem xét một trường hợp sử dụng nơi chúng tôi có một máy tính có một CPU một lõi. Điều này có nghĩa là các tác vụ cần được thực thi như một phần của ứng dụng không thể đạt được tiến bộ cùng một lúc vì bộ xử lý chỉ có khả năng làm việc chỉ một nhiệm vụ tại một thời điểm. Chạy đồng thời nhiều tác vụ, có nghĩa là bộ xử lý thực hiện chuyển đổi ngữ cảnh để nhiều tác vụ có thể bị tiến triển cùng một lúc.

Một trong những mục tiêu chính của đồng thời là ngăn chặn các nhiệm vụ chặn nhau bằng cách chuyển đổi qua lại, khi một trong các nhiệm vụ buộc phải chờ đợi (giả sử phản hồi từ tài nguyên bên ngoài). Ví dụ: Nhiệm vụ A tiến triển cho đến một điểm nhất định, CPU ngừng hoạt động trên Task As Nhiệm vụ B cho đến khi nó hoàn thành nhiệm vụ này, quá.

Một ứng dụng bao gồm hai nhiệm vụ đang được thực hiện đồng thời trong một lõi duy nhất được minh họa trong sơ đồ dưới đây.

Thực thi đồng thời - Nguồn: Tác giả

Mặt khác, trong nhiều tác vụ song song (hoặc thậm chí một số thành phần của một tác vụ) có thể chạy theo nghĩa đen cùng một lúc (ví dụ: trên bộ xử lý đa lõi hoặc trên máy có nhiều CPU). Do đó, không thể có sự song song trên các máy với một bộ xử lý duy nhất và lõi đơn.parallelism multiple tasks (or even several components of one task) can literally run at the same time (e.g on a multi-core processor or on a machine with multiple CPUs). Therefore, it is not possible to have parallelism on machines with a single processor and single core.

Song song: một điều kiện phát sinh khi ít nhất hai luồng đang thực hiện đồng thời.

- Hướng dẫn lập trình đa luồng của Sun Sun

Bây giờ, hãy để xem xét một trường hợp sử dụng nơi chúng tôi có một máy tính có một CPU một lõi. Điều này có nghĩa là các tác vụ cần được thực thi như một phần của ứng dụng không thể đạt được tiến bộ cùng một lúc vì bộ xử lý chỉ có khả năng làm việc chỉ một nhiệm vụ tại một thời điểm. Chạy đồng thời nhiều tác vụ, có nghĩa là bộ xử lý thực hiện chuyển đổi ngữ cảnh để nhiều tác vụ có thể bị tiến triển cùng một lúc.

Một trong những mục tiêu chính của đồng thời là ngăn chặn các nhiệm vụ chặn nhau bằng cách chuyển đổi qua lại, khi một trong các nhiệm vụ buộc phải chờ đợi (giả sử phản hồi từ tài nguyên bên ngoài). Ví dụ: Nhiệm vụ A tiến triển cho đến một điểm nhất định, CPU ngừng hoạt động trên Task As Nhiệm vụ B cho đến khi nó hoàn thành nhiệm vụ này, quá.

Một ứng dụng bao gồm hai nhiệm vụ đang được thực hiện đồng thời trong một lõi duy nhất được minh họa trong sơ đồ dưới đây.

Thực thi đồng thời - Nguồn: Tác giảproperty of a system or program and refers to how a single CPU (core) can make progress on multiple tasks seemingly at the same time (i.e. concurrently) while parallelism is the actual run-time behaviour of executing at least two tasks literally at the same time, in parallel. Additionally, it is important to highlight that both concurrency and parallelism could be combined during task execution. In fact, we could have all sort of combinations;

  • Mặt khác, trong nhiều tác vụ song song (hoặc thậm chí một số thành phần của một tác vụ) có thể chạy theo nghĩa đen cùng một lúc (ví dụ: trên bộ xử lý đa lõi hoặc trên máy có nhiều CPU). Do đó, không thể có sự song song trên các máy với một bộ xử lý duy nhất và lõi đơn.: This is also known as sequentialexecutionwhere tasks are executed strictly one after the other.
  • Song song: một điều kiện phát sinh khi ít nhất hai luồng đang thực hiện đồng thời.: This means that the tasks make progress seemingly at the same time, but in fact the system switches between various tasks that are concurrently in progress, until all of them are executed. Therefore, there is no true parallelism and thus no two tasks are being executed at exactly the same time.
  • Với sự song song, chúng tôi có thể tối đa hóa việc sử dụng tài nguyên phần cứng. Hãy xem xét kịch bản trong đó chúng ta có 16 lõi CPU - có lẽ sẽ thông minh hơn khi khởi chạy nhiều quy trình hoặc luồng để sử dụng tất cả các lõi này thay vì chỉ dựa vào một lõi duy nhất trong khi 15 còn lại không hoạt động.: This is a fairly rare scenario where only one task is being executed at any given time, but the task itself is broken down into sub-tasks that are being processed in parallel. Every task though, must be completed before the next task is picked up and executed.
  • Trong môi trường đa lõi, mỗi lõi có thể thực thi một tác vụ đúng lúc, như được minh họa trong sơ đồ dưới đây:: This could happen basically in two ways; The first is the simple parallel and concurrent execution where the application fires up multiple threads that are being executed on multiple CPUs and/or cores. The second way that this can be achieved is when the application is able to work on multiple tasks concurrently but at the same time it also breaks down each individual task into sub-tasks so these sub-tasks can eventually be executed in parallel.
Song song với đồng thời - Nguồn: Tác giả

Bây giờ chúng ta có một sự hiểu biết cơ bản về cách thức đồng thời và song song công việc, hãy để khám phá đa xử lý và đa luồng bằng cách sử dụng một số ví dụ trong Python.

Chủ đề trong Python

Một luồng là một chuỗi các hướng dẫn đang được thực thi trong bối cảnh của một quá trình. Một quy trình có thể sinh ra nhiều luồng nhưng tất cả chúng sẽ chia sẻ cùng một bộ nhớ.

Khi thử nghiệm với đa luồng trong Python trên các tác vụ ràng buộc CPU, cuối cùng bạn sẽ nhận thấy rằng việc thực thi không được tối ưu hóa và thậm chí nó có thể chạy chậm hơn khi sử dụng nhiều luồng. Thông thường, kỳ vọng sẽ là việc sử dụng mã đa luồng trên máy nhiều cõi nên tận dụng các lõi có sẵn và do đó tăng hiệu suất tổng thể.

Trên thực tế, một quá trình Python không thể chạy các luồng song song nhưng nó có thể chạy chúng đồng thời thông qua chuyển đổi ngữ cảnh trong các hoạt động ràng buộc I/O.

Hạn chế này thực sự được thực thi bởi Gil. Khóa thông dịch viên toàn cầu Python (GIL) ngăn chặn các luồng trong cùng một quy trình được thực hiện cùng một lúc.Python Global Interpreter Lock (GIL) prevents threads within the same process to be executed at the same time.

Gil, là một mutex bảo vệ quyền truy cập vào các đối tượng Python, ngăn chặn nhiều luồng thực thi các byte Python cùng một lúc - Python Wiki

Gil là cần thiết vì trình thông dịch Python không an toàn. Khóa toàn cầu này được thực thi mỗi khi chúng tôi cố gắng truy cập các đối tượng Python trong các luồng. Tại bất kỳ thời điểm nào, chỉ có một luồng có thể có được khóa cho một đối tượng cụ thể. Do đó, mã ràng buộc CPU sẽ không có mức tăng hiệu suất với đa luồng Python.not thread-safe. This global lock is enforced every time we attempt to access Python objects within threads. At any given time, only one thread can acquire the lock for a specific object. Therefore, CPU-bound code will have no performance gain with Python multi-threading.

Chi tiết triển khai CPython:

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ù các 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).

Nếu bạn muốn ứng dụng của mình sử dụng tốt hơn các tài nguyên tính toán của các máy đa lõi, bạn nên sử dụng multiprocessing hoặc concurrent.futures.ProcessPoolExecutor.

- Tài liệu Python

Bạn có thể đọc thêm về khóa phiên dịch toàn cầu của Python trong một trong những bài viết gần đây của tôi, nhưng thông tin được cung cấp bây giờ là quá đủ để hiểu làm thế nào khóa thông dịch toàn cầu giới hạn khả năng của các ứng dụng đa luồng trong Python (và có khả năng tại sao nó là bắt buộc ở nơi đầu tiên).

Bây giờ chúng ta có một sự hiểu biết về cách các ứng dụng đa luồng hoạt động trong Python, hãy để viết một số mã và tận dụng kỹ thuật này.

Trong Python, các luồng có thể được thực hiện với việc sử dụng mô -đun threading. Bây giờ, hãy để xem xét một chức năng được sử dụng để tải xuống một hình ảnh-đây rõ ràng là một nhiệm vụ ràng buộc I/O:

Ví dụ chức năng ràng buộc CPU-Nguồn: Tác giả

Sau đó, hãy để cố gắng tải xuống một vài hình ảnh từ Unplash bằng cách sử dụng đoạn mã bên dưới. Lưu ý rằng để chứng minh ảnh hưởng của việc luồng rõ ràng hơn, chúng tôi cố tình cố gắng tải xuống những hình ảnh này 5 lần (xem vòng lặp for):

Tải xuống hình ảnh từ Unplash với Python (Nhiệm vụ ràng buộc I/O) - Nguồn: Tác giả

Vì vậy, ứng dụng nhỏ của chúng tôi hoạt động tốt nhưng chúng tôi chắc chắn có thể làm tốt hơn và tối ưu hóa mã bằng cách tận dụng các chủ đề (đừng quên rằng việc tải xuống -Multiple- hình ảnh là một tác vụ ràng buộc I/O).

Tải xuống hình ảnh từ Unplash với luồng - Nguồn: Tác giả

Để tóm tắt lại, luồng trong Python cho phép nhiều luồng được tạo trong một quy trình duy nhất, nhưng do Gil, không ai trong số chúng sẽ chạy cùng một lúc. Chủ đề vẫn là một lựa chọn rất tốt khi chạy nhiều tác vụ ràng buộc I/O đồng thời. Bây giờ nếu bạn muốn tận dụng các tài nguyên tính toán trên các máy đa lõi, thì đa xử lý là cách để đi.Threading is still a very good option when it comes to running multiple I/O bound tasks concurrently. Now if you want to take advantage of computational resources on multi-core machines, then multi-processing is the way to go.

Bạn cũng nên lưu ý rằng luồng đi kèm với chi phí liên quan đến việc quản lý các luồng và do đó bạn nên tránh sử dụng chúng cho các tác vụ cơ bản. Ngoài ra, chúng cũng tăng sự phức tạp của chương trình, điều đó có nghĩa là việc gỡ lỗi có thể trở nên hơi khó khăn. Do đó, chỉ sử dụng luồng ở bất cứ nơi nào có một giá trị rõ ràng khi làm như vậy.

Đa xử lý trong Python

Bây giờ nếu chúng ta muốn tận dụng các hệ thống đa lõi và cuối cùng chạy các tác vụ trong bối cảnh thực sự song song, chúng ta cần thực hiện đa xử lý thay vì đa luồng.

Trong Python, việc xử lý đa xử lý có thể được thực hiện bằng mô-đun multiprocessing (hoặc concurrent.futures.ProcessPoolExecutor) có thể được sử dụng để sinh ra nhiều quy trình OS. Do đó, đa xử lý trong các bước bên Python, Gil và những hạn chế phát sinh từ nó vì mọi quy trình hiện sẽ có thông dịch viên riêng và do đó là Gil.multi-processing in Python side-steps the GIL and the limitations that arise from it since every process will now have its own interpreter and thus own GIL.

multiprocessing là một gói hỗ trợ các quy trình sinh sản bằng API tương tự như mô -đun multiprocessing0.

Gói multiprocessing cung cấp cả đồng thời địa phương và từ xa, bước hiệu quả là khóa thông dịch toàn cầu bằng cách sử dụng các quy trình phụ thay vì các luồng.

Do đó, mô -đun multiprocessing cho phép lập trình viên tận dụng đầy đủ nhiều bộ xử lý trên một máy nhất định. Nó chạy trên cả UNIX và Windows.

- Tài liệu Python

Trong phần trước, chúng tôi đã nói về việc luồng và chúng tôi đã thấy rằng việc luồng hoàn toàn không cải thiện các nhiệm vụ liên kết CPU. Điều này có thể đạt được với việc sử dụng đa xử lý. Hãy để sử dụng cùng một chức năng multiprocessing3 mà chúng tôi đã sử dụng trong phần trước, nhưng lần này thay vì multiprocessing0 chúng tôi sẽ sử dụng multiprocessing để tận dụng máy đa cõi của chúng tôi.

Bây giờ, hãy để Lừa xem xét một hoạt động ràng buộc CPU liên quan đến một hàm nối nhiều số nguyên ngẫu nhiên vào danh sách.consider a CPU-bound operation that involves a function which appends multiple random integers to a list.

Nhiệm vụ ràng buộc CPU-Nguồn: Tác giả

Bây giờ, hãy để giả sử chúng tôi muốn chạy chức năng này hai lần, như được minh họa dưới đây:

Nhiệm vụ ràng buộc CPU mà không cần đa xử lý-Nguồn: Tác giả

Và hãy để Lừa multiprocessing6 Thực hiện này và kiểm tra kết quả.

Bây giờ, hãy để Lừa lại mã của chúng tôi một chút và bây giờ sử dụng hai quy trình khác nhau để mỗi cuộc gọi đến chức năng được thực thi trong quy trình riêng của nó:

Đa xử lý với nhiệm vụ ràng buộc CPU-Nguồn: Tác giả

Và cuối cùng, hãy để Lừa ____ ____ và thực hiện và kiểm tra kết quả:

Chúng ta có thể thấy rõ rằng (mặc dù multiprocessing8 và multiprocessing9 lần vẫn giữ nguyên song song).

Để tóm tắt lại, có thể sử dụng đa xử lý trong Python khi chúng ta cần tận dụng sức mạnh tính toán từ một hệ thống đa lõi. Trong thực tế, mô -đun đa xử lý cho phép bạn chạy nhiều tác vụ và quy trình song song. Trái ngược với luồng, các bước phụ của multiprocessing bằng cách sử dụng các quy trình con thay vì các luồng và do đó nhiều quy trình có thể chạy theo nghĩa đen cùng một lúc. Kỹ thuật này chủ yếu phù hợp cho các nhiệm vụ gắn CPU.parallel. In contrast to threading, multiprocessing side-steps the GIL by using subprocesses instead of threads and thus multiple processes can run literally at the same time. This technique is mostly suitable for CPU-bound tasks.

Suy nghĩ cuối cùng

Trong bài viết hôm nay, chúng tôi đã giới thiệu hai trong số các khái niệm cơ bản nhất trong lập trình, cụ thể là đồng thời và song song và cách chúng khác nhau hoặc thậm chí được kết hợp khi thực hiện. Hơn nữa, chúng tôi đã thảo luận về việc luồng và đa xử lý và khám phá những ưu điểm và nhược điểm chính của chúng cũng như một vài trường hợp sử dụng cuối cùng có thể giúp bạn hiểu khi nào nên sử dụng cái này. Cuối cùng, chúng tôi đã trình bày cách thực hiện các ứng dụng có luồng hoặc đa xử lý với Python.

Tóm lại,

Luồng

  • Chủ đề chia sẻ cùng một bộ nhớ và có thể ghi và đọc từ các biến được chia sẻ
  • Do khóa thông dịch viên toàn cầu Python, hai luồng won đã được thực hiện cùng một lúc, nhưng đồng thời (ví dụ với chuyển đổi ngữ cảnh)
  • Hiệu quả cho các nhiệm vụ gắn I/O
  • Có thể được triển khai với mô -đun multiprocessing0

Multi-processing

  • Mọi quy trình đều có không gian bộ nhớ riêng
  • Mọi quy trình đều có thể chứa một quặng hơn/chủ đề
  • Có thể được sử dụng để đạt được sự song song bằng cách tận dụng các máy đa lõi vì các quy trình có thể chạy trên các lõi CPU khác nhau
  • Hiệu quả cho các nhiệm vụ gắn CPU
  • Có thể được thực hiện với multiprocessingModule (hoặc concurrent.futures.ProcessPoolExecutor)

Trở thành một thành viên và đọc mọi câu chuyện trên Medium. Phí thành viên của bạn trực tiếp hỗ trợ tôi và các nhà văn khác mà bạn đọc. Bạn cũng sẽ có quyền truy cập đầy đủ vào mọi câu chuyện trên Medium. and read every story on Medium. Your membership fee directly supports me and other writers you read. You’ll also get full access to every story on Medium.

Python có thể có nhiều chủ đề?

Để tóm tắt lại, luồng trong Python cho phép nhiều luồng được tạo trong một quy trình duy nhất, nhưng do Gil, không ai trong số chúng sẽ chạy cùng một lúc. Chủ đề vẫn là một lựa chọn rất tốt khi chạy nhiều tác vụ ràng buộc I/O đồng thời.threading in Python allows multiple threads to be created within a single process, but due to GIL, none of them will ever run at the exact same time. Threading is still a very good option when it comes to running multiple I/O bound tasks concurrently.

Làm thế nào để bạn chạy nhiều chủ đề trong Python?

Để sử dụng đa luồng, chúng ta cần nhập mô -đun luồng trong chương trình Python.Một phương thức start () được sử dụng để bắt đầu hoạt động của một luồng.Và nó chỉ gọi một lần cho mỗi luồng để việc thực thi luồng có thể bắt đầu.import the threading module in Python Program. A start() method is used to initiate the activity of a thread. And it calls only once for each thread so that the execution of the thread can begin.

Bạn có thể có bao nhiêu chủ đề trong Python?

Sự thật là, bạn có thể chạy nhiều luồng trong Python như bạn có bộ nhớ, nhưng tất cả các luồng trong một quy trình Python chạy trên một lõi máy duy nhất, vì vậy về mặt kỹ thuật chỉ có một luồng thực sự được thực hiện cùng một lúc.Điều này có nghĩa là các chủ đề Python thực sự chỉ hữu ích cho các hoạt động I/O đồng thời.

Là đa xử lý có thể trong Python?

Gói đa xử lý cung cấp cả đồng thời cục bộ và từ xa, bước hiệu quả là khóa thông dịch toàn cầu bằng cách sử dụng các quy trình phụ 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 đầy đủ nhiều bộ xử lý trên một máy nhất định., effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads. Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine.