Tại sao Python là luồng đơn?

Một trong những cuộc thảo luận sôi nổi nhất giữa các nhà phát triển mà tôi từng thấy ngoài tốc độ thực thi chậm của Python là xung quanh các vấn đề về phân luồng và rất nhiều người trong số họ phàn nàn về GIL [Khóa phiên dịch toàn cầu]. Một số thậm chí còn nói rằng Python và các ngôn ngữ khác không thực sự “đồng thời” và không thể mở rộng tốt

Trong blog trước đây của tôi, tôi đã thảo luận chi tiết về vấn đề đầu tiên giải thích khái niệm thực thi mã Python ở tốc độ C [https. //Trung bình. com/@hitechpundir/execute-python-code-at-the-speed-of-c-extending-python-93e081b53f04]

Bài viết này sẽ cố gắng giải quyết vấn đề thứ hai một cách chi tiết

Trong khi đồng thời xác định vấn đề, song song xác định việc thực hiện. Có nhiều giải pháp để đạt được điều này bao gồm phân luồng tiêu chuẩn [hoặc pthread] cho lập trình không đồng bộ, xử lý chuyển đổi, v.v. Mỗi một trong những mô hình này đều có những ưu và nhược điểm riêng phải được hiểu trước khi bạn là một lập trình viên thực sự có thể chọn sử dụng mô hình nào

Nhiều người không hiểu những ưu và nhược điểm của từng vấn đề chỉ tiếp cận vấn đề với giải pháp gần như phổ biến nhất hiện nay cho “vấn đề” đồng thời. Luồng và lập trình luồng. Và cách tiếp cận này sẽ là nguyên nhân khiến bạn đau đớn và phàn nàn. [Lưu ý cách tiếp cận của chúng tôi chứ không phải bản thân ngôn ngữ là vấn đề]

Luồng và GIL trong Python

Cả quy trình và luồng đều được tạo trong một ngôn ngữ lập trình nhất định và sau đó được lên lịch để chạy, bởi chính trình thông dịch [“luồng xanh”] hoặc bởi hệ điều hành [“luồng gốc”]

Guido nói để trả lời một câu hỏi luồng

“Tuy nhiên, bạn nói đúng, GIL không tệ như bạn nghĩ lúc đầu. bạn chỉ cần gỡ bỏ sự tẩy não mà bạn nhận được từ những người ủng hộ Windows và Java, những người dường như coi các luồng là cách duy nhất để tiếp cận các hoạt động đồng thời

Chỉ vì Java đã từng nhắm đến một hệ điều hành hộp giải mã tín hiệu không hỗ trợ nhiều không gian địa chỉ và chỉ vì việc tạo quy trình trong Windows từng chậm như chó, không có nghĩa là nhiều quy trình [với việc sử dụng IPC một cách hợp lý . ” https. //email. con trăn. org/pipermail/python-3000/2007-May/007414. html

GIL là khóa cấp thông dịch viên. Khóa này ngăn việc thực thi nhiều luồng cùng một lúc trong trình thông dịch Python. Mỗi luồng muốn chạy phải đợi GIL được giải phóng bởi luồng khác, điều đó có nghĩa là ứng dụng Python đa luồng của bạn thực sự là luồng đơn. GIL ngăn truy cập đồng thời vào các đối tượng Python bằng nhiều luồng

Bây giờ, câu hỏi xuất hiện trong đầu là “nếu chúng ta có GIL và một luồng phải sở hữu nó để thực thi trong trình thông dịch, thì điều gì quyết định xem GIL có nên được phát hành hay không?”

Câu trả lời là hướng dẫn mã byte. Khi một ứng dụng Python được thực thi, nó được biên dịch thành mã byte, các lệnh thực tế mà trình thông dịch sử dụng để thực thi ứng dụng. Thông thường, các tệp mã byte kết thúc bằng tên như “. pyc” hoặc “. pyo”. Một dòng nhất định của ứng dụng Python có thể là một mã byte đơn, trong khi những dòng khác, chẳng hạn như câu lệnh nhập, cuối cùng có thể mở rộng thành nhiều hướng dẫn mã byte cho trình thông dịch

Trình thông dịch CPython [đối với mã Python thuần túy] sẽ buộc GIL được giải phóng sau mỗi lệnh mã trăm byte. Điều này có nghĩa là nếu bạn có một dòng mã phức tạp hoạt động như một mã byte đơn thì GIL sẽ không được phát hành trong khoảng thời gian mà câu lệnh đó cần để chạy

Tuy nhiên, phần mở rộng C là ngoại lệ

Sử dụng Py_BEGIN_ALLOW_THREADS và Py_END_ALLOW_THREADS, bạn thực sự có thể nhận và giải phóng GIL một cách tự nguyện. [thêm về điều này có thể được trong một bài viết khác]

Py_BEGIN_ALLOW_THREADS

… Thực hiện một số thao tác chặn I/O…

Py_END_ALLOW_THREADS

Quay trở lại cuộc thảo luận chính, thực tế là GIL ngăn bạn với tư cách là một lập trình viên sử dụng đồng thời nhiều CPU. Tuy nhiên, Python với tư cách là một ngôn ngữ thì không

Cần lưu ý rằng GIL không ngăn quá trình chạy trên bộ xử lý khác của máy. Nó chỉ đơn giản là chỉ cho phép một luồng chạy cùng một lúc trong trình thông dịch

Vì vậy, đa xử lý không đa luồng sẽ cho phép bạn đạt được đồng thời thực sự

Hãy hiểu tất cả điều này thông qua một số điểm chuẩn vì chỉ có điều đó mới khiến bạn tin vào những gì đã nói ở trên. Và vâng, đó nên là cách để học - trải nghiệm thay vì chỉ đọc hoặc hiểu nó. Bởi vì nếu bạn đã trải qua một điều gì đó, thì không có lý lẽ nào có thể thuyết phục bạn về những suy nghĩ đối lập

import randomfrom threading import Threadfrom multiprocessing import Processsize = 10000000   # Number of random numbers to add to listthreads = 2 # Number of threads to createmy_list = []for i in xrange[0,threads]:    my_list.append[[]]def func[count, mylist]:    for i in range[count]:        mylist.append[random.random[]]def multithreaded[]:    jobs = []    for i in xrange[0, threads]:        thread = Thread[target=func,args=[size,my_list[i]]]        jobs.append[thread]    # Start the threads    for j in jobs:        j.start[]     # Ensure all of the threads have finished    for j in jobs:        j.join[]
def simple[]: for i in xrange[0, threads]: func[size,my_list[i]]
def multiprocessed[]: processes = [] for i in xrange[0, threads]: p = Process[target=func,args=[size,my_list[i]]] processes.append[p] # Start the processes for p in processes: p.start[] # Ensure all processes have finished execution for p in processes: p.join[]if __name__ == "__main__": multithreaded[] #simple[] #multiprocessed[]

kết quả điểm chuẩn

Để thực hiện đo điểm chuẩn, chúng tôi có thể sửa đổi tham số luồng trong tệp thành 2 , 3 , 4 để có kết quả bên dưới. Trong chức năng chính, chúng ta có thể chạy đa luồng, đơn giản hoặc đa xử lý cùng một lúc [bằng cách nhận xét hai cái khác như trên] và sử dụng

time python threadbenchmark.py

để có được thời gian tiêu thụ. [chúng ta chỉ nên nhìn vào kết quả thực tế để đo điểm chuẩn mà không phải lo lắng về người dùng và thời gian của hệ thống]

Thời gian thực hiện tính bằng giây cho 2, 3 và 4 luồng

                  simple    threading   multiprocessingthreads = 2       4.124      5.539       2.034threads = 3       6.391      13.772      3.376threads = 4       9.194      17.641      4.720

Vì vậy, luồng thậm chí còn chậm hơn so với thực thi đơn giản. Điều này được hiểu từ hành vi của GIL đã thảo luận ở trên và bây giờ chúng ta không nên ngạc nhiên

Thực sự những gì mang lại lợi ích hiệu suất về tốc độ thực thi là đa xử lý. Vì vậy, ngôn ngữ không giới hạn chúng ta ở tất cả. Tất nhiên, giống như đa luồng phải giải quyết các vấn đề về đồng bộ hóa, bế tắc, v.v. ; . [Giao tiếp giữa các quá trình] có thể được thảo luận trong một bài đăng khác

Vì vậy, chúng ta có thể dễ dàng kết luận rằng các luồng không nên được sử dụng cho các tác vụ bị ràng buộc bởi CPU. Tuy nhiên, cuộc thảo luận này không có nghĩa là chủ đề không hữu ích. Các chủ đề sau đó hữu ích trong Python ở đâu?

  • Trong các ứng dụng GUI để giữ cho chuỗi giao diện người dùng phản hồi nhanh
  • Nhiệm vụ IO [IO mạng hoặc IO hệ thống tập tin]

Theo dõi Practo trên twitter để cập nhật thường xuyên từ nhóm Kỹ thuật của chúng tôi. Nếu bạn thích bài viết này, vui lòng nhấn nút ❤ để giới thiệu nó. Điều này sẽ giúp những người dùng Phương tiện khác tìm thấy nó

Tại sao Python không đa luồng?

Python không hỗ trợ đa luồng vì Python trên trình thông dịch Cpython không hỗ trợ thực thi đa lõi thực sự thông qua đa luồng . Tuy nhiên, Python có thư viện luồng. GIL không ngăn luồng.

Python có thể chạy nhiều luồng không?

Tóm lại, phân 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, sẽ không có luồng nào trong số đó . Phân luồng vẫn là một tùy chọn rất tốt khi chạy đồng thời nhiều tác vụ ràng buộc I/O.

Luồng đơn và đa luồng trong Python là gì?

Các quy trình đơn luồng chứa việc thực thi các lệnh theo một trình tự duy nhất . Nói cách khác, một lệnh được xử lý tại một thời điểm. Ngược lại với các quy trình đơn luồng là các quy trình đa luồng. Các quy trình này cho phép thực hiện nhiều phần của chương trình cùng một lúc.

Các luồng Python có thể chạy trên nhiều lõi không?

Luồng Python không thể tận dụng nhiều lõi . Điều này là do một chi tiết triển khai nội bộ được gọi là GIL [khóa trình thông dịch toàn cầu] trong triển khai C của python [cPython] gần như chắc chắn là thứ bạn sử dụng.

Chủ Đề