paint-brush
Hiểu về Đa xử lý và Đa luồng trong Pythontừ tác giả@pragativerma
10,354 lượt đọc
10,354 lượt đọc

Hiểu về Đa xử lý và Đa luồng trong Python

từ tác giả Pragati Verma6m2022/08/22
Read on Terminal Reader
Read this story w/o Javascript

dài quá đọc không nổi

Đa luồng và Đa xử lý là hai cách phổ biến nhất để đạt được sự đồng thời và song song. Không có nhiều nhà phát triển hiểu được sự khác biệt giữa chúng và không chọn được để sử dụng. Trong bài viết này, chúng ta sẽ thảo luận về sự khác biệt. Chúng ta có thể sử dụng mô-đun Threading Python để hiểu và triển khai khái niệm. Mô-đun phân luồng cung cấp một API tinh vi để dễ dàng tạo ra nhiều luồng có thể được sử dụng khi cần nhiều sức mạnh xử lý hơn. Để làm điều này, bạn sẽ phải sử dụng một cái gì đó được gọi là ** Khóa ** hoặc ** Khóa thông dịch viên toàn cầu trong Python.

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Hiểu về Đa xử lý và Đa luồng trong Python
Pragati Verma HackerNoon profile picture


Đa luồng và Đa xử lý là hai cách phổ biến nhất để đạt được sự đồng thời và song song, tuy nhiên, không nhiều nhà phát triển hiểu được sự khác biệt giữa chúng và không chọn được hiệu quả để sử dụng khi nào.


Trong bài viết này, chúng ta sẽ thảo luận về sự khác biệt giữa Đa luồng và Đa xử lý cũng như cách quyết định những gì sẽ sử dụng và cách triển khai nó trong Python.


Chủ đề là gì?

Một luồng là một luồng thực thi độc lập. Về cơ bản, nó có thể được xem như một thành phần riêng lẻ nhẹ của một quy trình, có thể chạy song song. Phân luồng là một tính năng thường được cung cấp bởi hệ điều hành. Có thể có nhiều luồng trong một tiến trình, chia sẻ cùng một không gian bộ nhớ, có nghĩa là chúng chia sẻ mã được thực thi và các biến được khai báo trong chương trình với nhau.


Để hiểu rõ hơn điều này, chúng ta hãy xem xét một ví dụ về các chương trình đang chạy trên máy tính xách tay của bạn ngay bây giờ. Có thể bạn đang đọc bài viết này với nhiều tab đang mở trong trình duyệt của mình. Trong khi đó, bạn có ứng dụng Spotify trên máy tính để bàn đang mở để nghe nhạc. Giờ đây, trình duyệt và ứng dụng Spotify dành cho máy tính để bàn giống như hai quy trình riêng biệt có thể sử dụng một số quy trình hoặc chuỗi để đạt được sự song song. Vì vậy, các tab khác nhau trong trình duyệt của bạn có thể được chạy trong các chuỗi khác nhau. Tương tự, Spotify có thể phát nhạc bằng một chuỗi và sử dụng một chuỗi khác để tải xuống bài hát yêu thích của bạn từ internet và sử dụng một chuỗi thứ ba để hiển thị giao diện người dùng. Và điều này được gọi là Đa luồng.


Đa luồng trong Python là gì?

Đa luồng, như tên cho thấy, là một nhiệm vụ hoặc một hoạt động có thể thực hiện nhiều luồng cùng một lúc. Đây là một kỹ thuật phổ biến giúp sắp xếp hợp lý nhiều tác vụ liên tiếp nhanh chóng cùng một lúc và tạo điều kiện chia sẻ tài nguyên nhanh chóng và dễ dàng giữa nhiều luồng với luồng chính.


Hình ảnh sau giải thích Đa luồng trong Python:



Python là một ngôn ngữ tuyến tính, nhưng chúng ta có thể sử dụng mô-đun Threading Python để hiểu và triển khai khái niệm Đa luồng trong Python. Mô-đun phân luồng cung cấp một API tinh vi để dễ dàng tạo ra nhiều luồng có thể được sử dụng khi cần nhiều sức mạnh xử lý hơn.


Nó có thể được sử dụng như hình dưới đây:


 import threading from queue import Queue import time def testThread(num): print num if __name__ == '__main__': for i in range(5): t = threading.Thread(target=testThread, arg=(i,)) t.start()


Trong đoạn mã trên, target được sử dụng làm đối tượng có thể gọi, args để chuyển các tham số cho hàm và start bắt đầu chuỗi.


Bây giờ, ở đây có một thứ thú vị - ổ khóa.


Khóa thông dịch viên toàn cầu

Thường có những trường hợp trong lập trình mà bạn muốn các luồng của mình có thể sửa đổi hoặc sử dụng các biến phổ biến cho các luồng. Tuy nhiên, để làm điều này, bạn sẽ phải sử dụng một thứ được gọi là Khóa hoặc Khóa thông dịch viên toàn cầu (GIL) trong Python.


Từ Python wiki :


Trong CPython, khóa thông dịch viên 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 các mã byte Python cùng một lúc. Khóa này là cần thiết chủ yếu vì quản lý bộ nhớ của CPython không an toàn theo luồng.


Ở cấp thông dịch, Python về cơ bản tuần tự hóa các hướng dẫn. Để bất kỳ luồng nào có thể chạy bất kỳ chức năng nào, trước tiên nó phải nhận được một khóa toàn cục. Bởi vì chỉ một luồng có thể đạt được khóa đó tại một thời điểm, trình thông dịch cuối cùng phải thực hiện các lệnh một cách tuần tự. Kiến trúc này giúp quản lý bộ nhớ an toàn theo luồng, nhưng nó không thể sử dụng nhiều lõi CPU.


Nói một cách đơn giản, bất cứ khi nào một hàm muốn sử dụng hoặc sửa đổi một biến, nó sẽ khóa biến đó lại để nếu bất kỳ hàm nào khác muốn sử dụng hoặc sửa đổi biến cụ thể đó, nó sẽ phải đợi cho đến khi biến đó được mở khóa.


Hãy xem xét hai hàm mà mỗi hàm lặp lại một biến. Bạn có thể sử dụng khóa để đảm bảo rằng một hàm có thể đọc biến, chạy tính toán và ghi lại vào nó trước khi một hàm khác có thể, để chúng ta có thể tránh bị hỏng dữ liệu.


Các trường hợp sử dụng để phân luồng đột biến trong Python

Phân luồng bằng Python hữu ích hơn cho các hoạt động I / O hoặc tác vụ liên kết mạng, chẳng hạn như chạy tập lệnh, chẳng hạn như trong trường hợp quét web hơn là các tác vụ có thể sử dụng nhiều CPU. Một ví dụ khác là Tensorflow , sử dụng một nhóm luồng để chuyển đổi dữ liệu song song.


Ngoài các ứng dụng này, Giao diện người dùng đồ họa (GUI) luôn sử dụng Đa luồng để làm cho các ứng dụng phản hồi và tương tác. Một ví dụ phổ biến có thể là một chương trình chỉnh sửa văn bản mà ngay khi người dùng nhập văn bản, nó sẽ hiển thị trên màn hình. Ở đây một luồng xử lý đầu vào của người dùng trong khi luồng kia xử lý tác vụ hiển thị nó. Chúng tôi có thể thêm nhiều chủ đề hơn để có nhiều chức năng hơn như kiểm tra chính tả, tự động hoàn thành, v.v.


Bây giờ, đã thảo luận chi tiết về các luồng, chúng ta hãy chuyển sang các quy trình.


Quy trình là gì?

Một tiến trình chỉ đơn giản là một phiên bản của chương trình máy tính đang được thực thi. Mỗi tiến trình có không gian bộ nhớ riêng được sử dụng để lưu các lệnh đang được chạy và bất kỳ dữ liệu nào mà nó cần truy cập hoặc lưu trữ để thực thi mã. Do đó, quá trình tạo ra một quá trình tốn nhiều thời gian và chậm hơn so với một chuỗi.


Như chúng ta đã thảo luận trước đó, khi chúng ta đang chạy nhiều ứng dụng trên máy tính để bàn của mình, mỗi ứng dụng là một quá trình và khi nào thực hiện các quá trình này cùng một lúc, nó được gọi là Đa xử lý.


Multiprocessing trong Python là gì?

Đa xử lý là khả năng của một bộ xử lý để thực hiện đồng thời một số tác vụ không liên quan. Nó cho phép bạn tạo các chương trình có thể chạy đồng thời, bỏ qua Khóa thông dịch toàn cầu (GIL) và sử dụng toàn bộ lõi CPU để thực thi hiệu quả các tác vụ.


Mặc dù khái niệm Đa xử lý về cơ bản khác với Đa luồng, nhưng cú pháp hoặc cách sử dụng của chúng trong Python là khá giống nhau. Tương tự như mô-đun Luồng, chúng ta có một mô-đun Đa xử lý bằng Python giúp tạo ra các quy trình khác nhau, trong đó mỗi quy trình có trình thông dịch Python và GIL của riêng nó.



Vì các tiến trình không chia sẻ cùng một bộ nhớ, chúng không thể sửa đổi đồng thời cùng một bộ nhớ, giúp chúng ta tránh khỏi nguy cơ gặp bế tắc hoặc nguy cơ hỏng dữ liệu.


Nó có thể được sử dụng như hình dưới đây:


 import multiprocessing def spawn(num): print(num) if __name__ == '__main__': for i in range(5): p = multiprocessing.Process(target=spawn, args=(i,)) p.start() p.join() # this line allows you to wait for processes


Các trường hợp sử dụng để xử lý Mutlip trong Python

Như chúng ta đã thảo luận trước đó, Mutliprocessing là một lựa chọn khôn ngoan hơn trong trường hợp các tác vụ có nhiều CPU và không có bất kỳ hoạt động I / O hoặc tương tác người dùng nào.


Sự khác biệt, Ưu điểm và Hạn chế

Dưới đây là một số điểm để tóm tắt sự khác biệt, ưu điểm và nhược điểm của Đa xử lý và Đa luồng:

  • Các luồng chia sẻ cùng một không gian bộ nhớ trong khi mỗi tiến trình có không gian bộ nhớ riêng.
  • Chia sẻ các đối tượng giữa các luồng đơn giản hơn, nhưng bạn phải thực hiện các biện pháp phòng ngừa bổ sung cho việc đồng bộ hóa đối tượng để đảm bảo rằng hai luồng không ghi vào cùng một đối tượng tại cùng một thời điểm và điều kiện chủng tộc không phát sinh.
  • Lập trình đa luồng dễ bị lỗi hơn là Đa xử lý vì chi phí lập trình được bổ sung cho đồng bộ hóa đối tượng.
  • Quá trình sinh sản tốn nhiều thời gian và tài nguyên hơn các luồng vì chúng có chi phí thấp hơn các quy trình.
  • Các luồng không thể đạt được sự song song hoàn toàn bằng cách tận dụng nhiều lõi CPU do các ràng buộc GIL trong Python. Không có những ràng buộc như vậy với đa xử lý.
  • Hệ điều hành xử lý lập lịch quy trình, trong khi trình thông dịch Python xử lý lập lịch luồng.
  • Các tiến trình con có thể bị gián đoạn và bị giết, nhưng các tiến trình con thì không thể. Bạn phải đợi các chủ đề kết thúc hoặc tham gia.


Đa xử lý so với Đa luồng

Sự kết luận

Chúng ta có thể rút ra các kết luận sau từ cuộc thảo luận này:

  • Phân luồng được khuyến khích cho các chương trình cần IO hoặc tương tác của người dùng.
  • Đối với các ứng dụng đòi hỏi nhiều tính toán, bị ràng buộc bởi CPU, nên sử dụng đa xử lý.


Bây giờ bạn đã hiểu cách hoạt động của Đa xử lý và Đa luồng trong Python và cách chúng so sánh, bạn có thể viết mã một cách hiệu quả và áp dụng hai cách tiếp cận trong nhiều trường hợp khác nhau.


Tôi hy vọng bạn thấy bài viết này hữu ích. Hãy đọc tiếp!