HomeLập trìnhPythonNhững gì bạn...

Những gì bạn cần biết.


bởi Timber.io

HS26etJFGfMC8x2cZbKpLznEx-A790oyvnSs
Ảnh của Josep Castells trên Bapt

Luồng là gì? Tại sao bạn có thể muốn nó?

Python là một ngôn ngữ tuyến tính. Tuy nhiên, mô-đun luồng có ích khi bạn muốn có thêm một chút sức mạnh xử lý.

Luồng trong Python không thể được sử dụng để tính toán CPU song song. Nhưng nó hoàn hảo cho các hoạt động I/O chẳng hạn như quét web, vì bộ xử lý đang chờ dữ liệu.

Phân luồng đang thay đổi trò chơi, bởi vì nhiều tập lệnh liên quan đến mạng/dữ liệu I/O dành phần lớn thời gian của chúng để chờ dữ liệu từ một nguồn từ xa.

Vì các bản tải xuống có thể không được liên kết (ví dụ: nếu bạn đang quét các trang web riêng biệt), bộ xử lý có thể tải xuống song song từ các nguồn dữ liệu khác nhau và kết hợp kết quả ở cuối.

Đối với các quy trình sử dụng nhiều CPU, có rất ít lợi ích khi sử dụng mô-đun phân luồng.

ovUCmUeZrbYCgom4gc3TcPP9EZtq4INvmwTa

Threading được bao gồm trong thư viện tiêu chuẩn:

import threading from queueimport Queueimport time

Bạn có thể dùng target là đối tượng có thể gọi được, args để truyền tham số cho hàm và start để bắt đầu chủ đề.

def testThread(num):    print numif __name__ == '__main__':    for i in range(5):        t = threading.Thread(target=testThread, arg=(i,))        t.start()

Nếu bạn chưa bao giờ nhìn thấy if __name__ == '__main__': trước đây, về cơ bản, đó là một cách để đảm bảo mã được lồng bên trong nó sẽ chỉ chạy nếu tập lệnh được chạy trực tiếp (không được nhập).

Khoá

Bạn sẽ thường muốn các luồng của mình có thể sử dụng hoặc sửa đổi các biến phổ biến giữa các luồng. Để làm điều này, bạn sẽ phải sử dụng một cái gì đó được gọi là lock.

Bất cứ khi nào một hàm muốn sửa đổi một biến, nó sẽ khóa biến đó. Khi một chức năng khác muốn sử dụng một biến, nó phải đợi cho đến khi biến đó được mở khóa.

Đọc thêm  Đang tải tệp JSON bằng Python – Cách đọc và phân tích cú pháp JSON
7tzH0eWzoj2WDCWtQ4ofrUxBXhFBjcQ2eZVW

Hãy tưởng tượng hai hàm mà cả hai đều lặp lại một biến bằng 1. Khóa cho phép bạn đảm bảo rằng một hàm có thể truy cập vào biến đó, thực hiện các phép tính và ghi lại vào biến đó trước khi một hàm khác có thể truy cập vào cùng một biến.

Bạn có thể sử dụng khóa in để đảm bảo rằng mỗi lần chỉ có thể in một luồng. Điều này giúp văn bản không bị lộn xộn (và gây hỏng dữ liệu) khi bạn in.

Trong đoạn mã dưới đây, chúng tôi có 10 công việc mà chúng tôi muốn hoàn thành và 5 công nhân sẽ thực hiện công việc đó:

print_lock = threading.Lock()def threadTest():    # when this exits, the print_lock is released    with print_lock:        print(worker)def threader():  while True:    # get the job from the front of the queue    threadTest(q.get())    q.task_done()q = Queue()for x in range(5):    thread = threading.Thread(target = threader)    # this ensures the thread will die when the main thread dies    # can set t.daemon to False if you want it to keep running    t.daemon = True    t.start()for job in range(10):    q.put(job)

Đa luồng không phải lúc nào cũng là giải pháp hoàn hảo

Tôi thấy rằng nhiều hướng dẫn có xu hướng bỏ qua những mặt tiêu cực của việc sử dụng công cụ mà họ vừa cố dạy cho bạn. Điều quan trọng là phải hiểu rằng có cả ưu và nhược điểm liên quan đến việc sử dụng tất cả các công cụ này. Ví dụ:

  1. Có chi phí liên quan đến việc quản lý luồng, vì vậy bạn không muốn sử dụng nó cho các tác vụ cơ bản (như ví dụ)
  2. Phân luồng làm tăng độ phức tạp của chương trình, điều này có thể khiến việc gỡ lỗi trở nên khó khăn hơn
Đọc thêm  Bộ Python – Hoạt động và ví dụ

Đa xử lý là gì? Nó khác với luồng như thế nào?

Nếu không có đa xử lý, các chương trình Python gặp sự cố khi tối đa hóa thông số kỹ thuật của hệ thống do GIL (Khóa Phiên Dịch Toàn Cầu). Python không được thiết kế vì máy tính cá nhân có thể có nhiều hơn một lõi (điều này cho bạn biết tuổi của ngôn ngữ này).

GIL là cần thiết vì Python không an toàn cho luồng và có một khóa được thi hành trên toàn cầu khi truy cập một đối tượng Python. Mặc dù không hoàn hảo nhưng đây là một cơ chế quản lý bộ nhớ khá hiệu quả. Chúng ta có thể làm gì?

Đa xử lý cho phép bạn tạo các chương trình có thể chạy đồng thời (bỏ qua GIL) và sử dụng toàn bộ lõi CPU của bạn. Mặc dù về cơ bản nó khác với thư viện luồng, nhưng cú pháp khá giống nhau. Thư viện đa xử lý cung cấp cho mỗi quy trình trình thông dịch Python riêng và mỗi GIL của riêng chúng.

Do đó, các vấn đề thông thường liên quan đến phân luồng (chẳng hạn như hỏng dữ liệu và bế tắc) không còn là vấn đề nữa. Vì các tiến trình không chia sẻ bộ nhớ nên chúng không thể sửa đổi đồng thời cùng một bộ nhớ.

Bắt đầu nào

import multiprocessingdef spawn():  print('test!')if __name__ == '__main__':  for i in range(5):    p = multiprocessing.Process(target=spawn)    p.start()

Nếu bạn có cơ sở dữ liệu dùng chung, bạn muốn đảm bảo rằng bạn đang đợi các quy trình có liên quan kết thúc trước khi bắt đầu các quy trình mới.

for i in range(5):  p = multiprocessing.Process(target=spawn)  p.start()  p.join() # this line allows you to wait for processes

Nếu bạn muốn chuyển đối số cho quy trình của mình, bạn có thể làm điều đó với args:

import multiprocessingdef spawn(num):  print(num)if __name__ == '__main__':  for i in range(25):    ## right here    p = multiprocessing.Process(target=spawn, args=(i,))    p.start()

Đây là một ví dụ rõ ràng, bởi vì các con số không đến theo thứ tự mà bạn mong đợi (không có p.join()).

Đọc thêm  strftime() Python – Hướng dẫn định dạng ngày giờ

nhược điểm

Đối với phân luồng, vẫn còn những hạn chế với đa xử lý… bạn phải chọn thuốc độc của mình:

  1. Có chi phí I/O do dữ liệu bị xáo trộn giữa các quy trình
  2. Toàn bộ bộ nhớ được sao chép vào từng quy trình con, điều này có thể tốn nhiều chi phí cho các chương trình quan trọng hơn

Phần kết luận

Khi nào bạn nên sử dụng đa luồng so với đa xử lý?

  • Nếu mã của bạn có nhiều mức sử dụng I/O hoặc Mạng, thì đa luồng là lựa chọn tốt nhất của bạn vì chi phí thấp.
  • Nếu bạn có GUI, hãy sử dụng đa luồng để chuỗi giao diện người dùng của bạn không bị khóa.
  • Nếu mã của bạn bị ràng buộc bởi CPU, bạn nên sử dụng đa xử lý (nếu máy của bạn có nhiều lõi)

Tuyên bố miễn trừ trách nhiệm: chúng tôi là công ty khai thác gỗ tại đây @ Timber. Chúng tôi rất vui nếu bạn dùng thử sản phẩm của chúng tôi (nó thực sự rất tuyệt!), nhưng đó là tất cả những gì chúng tôi sẽ quảng cáo về nó.

Nếu bạn muốn nhận thêm bài đăng từ Timber trong hộp thư đến của mình, vui lòng đăng ký tại đây. Chúng tôi hứa sẽ không có thư rác, chỉ có nội dung tuyệt vời hàng tuần.

TfypoIZnTArPPIDyCyeOzyDi8ybZKDcqnaq6

Được xuất bản lần đầu tại Timber.io.



Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status