Trước đây, chúng tôi đã xem xét cách bạn có thể cố gắng đạt được đồng thời với Python bằng cách sử dụng đa luồng, bạn có thể tìm thấy hướng dẫn tại đây. Hướng dẫn đa luồng Python
Bây giờ chúng ta sẽ xem xét cách chúng ta có thể bỏ qua Khóa thông dịch viên toàn cầu giới hạn đã ngăn chặn hiệu quả các ứng dụng đa luồng của chúng ta thực sự đồng thời bằng cách sử dụng mô-đun Python đa xử lý
Song song vs Đồng thời
Vì vậy, trước khi chúng ta tìm hiểu sâu hơn về mô-đun đa xử lý, bạn nên đảm bảo rằng bạn biết những lợi ích của việc sử dụng đa xử lý so với đa luồng. Nguyên tắc chung là, nếu bạn đang cố gắng cải thiện hiệu suất của các tác vụ liên quan đến CPU, đa xử lý là thứ bạn muốn sử dụng. Tuy nhiên, nếu nhiệm vụ cụ thể của bạn là Đầu vào/Đầu ra bị ràng buộc, thì nhìn chung bạn sẽ muốn sử dụng đa luồng để cải thiện hiệu suất của các ứng dụng của mình
Một ví dụ đơn giản
Hãy bắt đầu bằng cách xây dựng một chương trình Python thực sự đơn giản sử dụng mô-đun đa xử lý
Trong ví dụ này, tôi sẽ chỉ cho bạn cách sinh ra nhiều quy trình cùng một lúc và mỗi quy trình sẽ xuất ra số ngẫu nhiên mà chúng sẽ tính toán bằng cách sử dụng mô-đun ngẫu nhiên
from multiprocessing import Process, Queue
import random
def rand_num[]:
num = random.random[]
print[num]
if __name__ == "__main__":
queue = Queue[]
processes = [Process[target=rand_num, args=[]] for x in range[4]]
for p in processes:
p.start[]
for p in processes:
p.join[]
Chạy cái này sau đó sẽ in ra một mảng gồm 4 số thập phân khác nhau trong khoảng từ 0 đến 1 như vậy
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
Bây giờ, điều quan trọng cần lưu ý ở đây là mỗi số ngẫu nhiên này được tạo trong một quy trình Python hoàn toàn riêng biệt được tạo với sự trợ giúp của mô-đun đa xử lý
Mỗi quy trình riêng biệt này đều có phiên bản riêng của Khóa phiên dịch toàn cầu và mỗi quy trình này có thể được chạy trên nhiều lõi CPU. Bây giờ, hãy tưởng tượng chúng ta đang làm một việc gì đó sử dụng nhiều CPU hơn là chỉ tạo một số ngẫu nhiên duy nhất. Đây là lúc mô-đun đa xử lý thực sự bắt đầu tỏa sáng
hồ bơi
Trong ví dụ trước, chúng tôi đã xem xét cách chúng tôi có thể tăng tốc các quy trình riêng lẻ, điều này có thể tốt cho loại ứng dụng chạy và hoàn thành, nhưng khi nói đến các ứng dụng chạy lâu hơn, tốt hơn là tạo một
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
4 chạy lâu hơn . Điều này giúp tránh phải tạo và hủy một quy trình mỗi khi bạn có một tác vụ mới cần thực thi và sau đó có thể cải thiện hiệu suất của các ứng dụng của bạnimport multiprocessing as mp
def my_func[x]:
print[x**x]
def main[]:
pool = mp.Pool[mp.cpu_count[]]
result = pool.map[my_func, [4,2,3]]
if __name__ == "__main__":
main[]
Bây giờ, nếu chúng ta thực hiện điều này, chúng ta sẽ thấy
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
5 của mình đang được thực thi với mảng Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
0 được ánh xạ làm đầu vào cho mỗi lệnh gọi hàm này python3.6 main.py
256
4
27
Hãy mở rộng điều này một chút để giới thiệu một số khái niệm chính ở đây
import multiprocessing as mp
def my_func[x]:
print[mp.current_process[]]
return x**x
def main[]:
pool = mp.Pool[mp.cpu_count[]]
result = pool.map[my_func, [4,2,3,5,3,2,1,2]]
result_set_2 = pool.map[my_func, [4,6,5,4,6,3,23,4,6]]
print[result]
print[result_set_2]
if __name__ == "__main__":
main[]
Vì vậy, chúng tôi đã thêm câu lệnh in thứ hai vào hàm
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
5. Điều này là để làm nổi bật quy trình nào trong nhóm của chúng tôi sẽ thực hiện một tác vụ cụ thể. Chúng tôi cũng đã thay đổi từ Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
2 thành Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
3 để chúng tôi có thể xem kết quả của nhóm quy trình của mìnhTrong hàm
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
4 của chúng tôi, chúng tôi đã thêm một vài giá trị khác vào mảng trong một Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
5 để chúng tôi có thể thực sự kiểm tra mức độ của các worker trong nhóm quy trình của chúng tôi. Chúng tôi cũng đang in ra các kết quả hiện sẽ được điền nhờ các tờ khai mới được thêm vào trong Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
5 của chúng tôiKhi chúng ta thực hiện điều này, chúng ta sẽ thấy đầu ra sau
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
0Như bạn có thể thấy, mỗi công việc của chúng tôi được thực hiện bởi một trong số
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
7 công nhân tồn tại trong nhóm. Các quy trình này được tái sử dụng để ngăn chặn nhiệm vụ tốn kém trong việc hủy và tạo các quy trình mới và thực hiện tiếp theoTruyền dữ liệu giữa các tiến trình
Khi thực hiện lập trình đồng thời, cách tốt nhất thường là tránh chia sẻ trạng thái càng nhiều càng tốt. Tuy nhiên, khi bạn thực sự cần có một số dạng dữ liệu được chia sẻ thì mô-đun đa xử lý sẽ cung cấp một số cách để thực hiện việc đó
hàng đợi
Các đối tượng hàng đợi là một cấu trúc dữ liệu FIFO, là luồng và xử lý an toàn, khiến chúng trở nên hoàn hảo để truyền dữ liệu giữa các quy trình khác nhau mà không có khả năng làm hỏng dữ liệu. Việc sử dụng chúng tương đối đơn giản, chúng ta có thể mở rộng
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
2Điều này sẽ xuất ra như sau
Elliots-MacBook-Pro:Networking elliotforbes$ python processing.py
0.090906474002
0.306163229303
0.995446921388
0.0320995066016
3Sự kết luận
Nhìn chung, mô-đun MultiProcessing của Python rất tuyệt vời cho những bạn muốn vượt qua những hạn chế của Khóa phiên dịch toàn cầu cản trở hiệu suất của đa luồng trong python
Tôi hy vọng điều này hữu ích, nếu bạn cảm thấy bất cứ điều gì khác cần thêm vào hướng dẫn này, hãy cho tôi biết trong phần nhận xét bên dưới. Ngoài ra, vui lòng theo dõi tôi trên twitter để biết các thông báo cập nhật và tất cả các bài báo lập trình mới nhất. @Elliot_f