Trong bài viết này, chúng ta sẽ xử lý đa chức năng chỉ trong 2 dòng mã. Trong trường hợp của chúng tôi, điều này sẽ giúp mã của chúng tôi tăng tốc đáng kể. Trước tiên, chúng ta sẽ tìm hiểu xem khi nào đa xử lý là một ý tưởng hay, sau đó chúng ta sẽ xem cách áp dụng 3 loại đa xử lý và thảo luận khi nào nên áp dụng loại nào. Hãy viết mã
Nhưng trước tiên
Trước khi đi sâu vào chủ đề của chúng ta về cách áp dụng đa xử lý, chúng ta sẽ phải chuẩn bị một số thứ. Trước tiên, chúng ta sẽ thảo luận về một số thuật ngữ và xác định xem khi nào đa xử lý là con đường phù hợp
Sau đó, chúng ta sẽ tạo một hàm ví dụ mà chúng ta có thể sử dụng làm minh họa trong bài viết này
Đồng thời so với song song - phân luồng so với đa xử lý
Có hai cách để “làm nhiều việc cùng lúc” trong Python. luồng và đa xử lý. Trong bài viết này, chúng tôi sẽ tập trung vào cái sau. Một sự khác biệt ngắn
- luồng chạy mã đồng thời. chúng tôi có một CPU đang hoạt động nhanh chóng chuyển đổi giữa nhiều luồng
- đa xử lý chạy mã song song. chúng tôi có nhiều CPU đang hoạt động, mỗi CPU chạy mã của riêng chúng
VÌ VẬY trong bài viết này, chúng tôi sẽ trình bày cách chạy mã song song. Nếu bạn quan tâm đến sự khác biệt giữa phân luồng và đa xử lý và khi nào áp dụng cái nào;
Nói chung, đa xử lý là ý tưởng đúng đắn nếu mã của bạn liên quan đến nhiều tính toán và nếu mỗi quy trình ít nhiều độc lập [vì vậy các quy trình không phải đợi lẫn nhau/cần đầu ra của quy trình khác]
Đa tác vụ trong Python. Tăng tốc chương trình của bạn gấp 10 lần bằng cách thực hiện đồng thời mọi thứ
Hướng dẫn từng bước để áp dụng các luồng và quy trình nhằm tăng tốc mã của bạn
hướng tới khoa học dữ liệu. com
Tạo một ví dụ cho bài viết này
Trong bài viết này, chúng tôi sẽ giả vờ có một công ty phân tích hình ảnh. Khách hàng có thể gửi cho chúng tôi một hoặc nhiều hình ảnh, chúng tôi sẽ phân tích và gửi lại
Hiện tại chúng tôi chỉ có một chức năng. get_most_popular_color[]
; . Nó trả về đường dẫn đến hình ảnh, giá trị rgb của màu và tỷ lệ pixel có màu này. Kiểm tra mã nguồn ở đây
Chức năng mục tiêu của chúng tôi [hình ảnh của tác giả]
Hàm này phù hợp với MP vì phải tính toán nhiều;
Tiêu diệt Duck Hunt với OpenCV — phân tích hình ảnh cho người mới bắt đầu
Viết mã sẽ đánh bại mọi điểm số Duck Hunt cao
hướng tới khoa học dữ liệu. com
phần mã. áp dụng chức năng của chúng tôi bình thường và sử dụng MP
Chúng tôi nhận được 12 hình ảnh từ khách hàng của mình; . 2 và 2MB. Tôi đã lưu trữ tất cả các đường dẫn đến hình ảnh trong một mảng chuỗi như bên dưới. Trước khi chúng tôi áp dụng đa xử lý cho chức năng của mình, chúng tôi sẽ chạy chức năng get_most_popular_color[]
bình thường để chúng tôi có thứ gì đó để so sánh với
image_paths = [
'images/puppy_1.png',
'images/puppy_2.png',
'images/puppy_3.png',
'images/puppy_4_small.png',
'images/puppy_5.png',
'images/puppy_6.png',
'images/puppy_7.png',
'images/puppy_8.png',
'images/puppy_9.png',
'images/puppy_10.png',
'images/puppy_11.png',
'images/puppy_12.png',
]
1. Cách thông thường. chạy liên tiếp
Cách rõ ràng nhất để xử lý 12 hình ảnh của chúng tôi là lặp qua chúng và xử lý chúng lần lượt
Không có gì đặc biệt ở đây. chúng ta chỉ cần gọi hàm cho mỗi hình ảnh trong một mảng image_paths. Sau khi thêm một số bản in để cho chúng tôi biết thêm một chút về thời gian thực hiện, chúng tôi nhận được đầu ra sau
Như bạn thấy, chúng tôi xử lý và in ra kết quả của từng hình ảnh, lần lượt từng hình ảnh. Tất cả trong tất cả quá trình mất hơn 8 giây một chút
Khi nào thì sử dụng cái này?
Phương pháp này phù hợp nếu thời gian của bạn không quan trọng và bạn muốn kết quả của mình theo thứ tự, cái này nối tiếp cái kia. Ngay khi image1 sẵn sàng, chúng tôi có thể gửi kết quả lại cho khách hàng
Tại sao Python quá chậm và làm thế nào để tăng tốc nó
Hãy nhìn vào bên trong để xem nút thắt cổ chai của Python nằm ở đâu
hướng tới khoa học dữ liệu. com
2. Cách thông thường. sử dụng bản đồ
Một cách khác để chạy hàm là áp dụng hàm map
của Python. Sự khác biệt chính là nó chặn cho đến khi tất cả các chức năng được thực thi, nghĩa là chúng ta chỉ có thể truy cập kết quả sau khi hình ảnh 12 được xử lý. Điều này có vẻ giống như một sự hạ cấp nhưng nó giúp chúng ta hiểu rõ hơn về các phần tiếp theo của bài viết này
Trong kết quả bên dưới, bạn sẽ thấy rằng chúng tôi chỉ có thể truy cập kết quả sau khi mỗi chức năng đã hoàn thành, nói cách khác. sử dụng map
trên các chức năng chặn kết quả. Bạn có thể thấy hậu quả của điều này trong đầu ra
Tất cả các dòng được in ở 8. 324 giây; . Điều này chứng tỏ rằng tất cả các chức năng phải hoàn thành trước khi chúng tôi có thể truy cập kết quả
Khi nào thì sử dụng cái này?
Khi một khách hàng gửi một loạt hình ảnh, chúng tôi sẽ muốn xử lý chúng và gửi lại một tin nhắn chứa tất cả các kết quả. Chúng tôi sẽ không gửi email cho khách hàng cho từng kết quả riêng lẻ
Cython cho người mới bắt đầu tuyệt đối. Mã nhanh hơn 30 lần trong hai bước đơn giản
Biên dịch mã Python dễ dàng cho các ứng dụng cực nhanh
hướng tới khoa học dữ liệu. com
3. đa xử lý. bản đồ
Chúng tôi không muốn đợi 8 giây, điều đó mất quá nhiều thời gian. Trong phần này, chúng ta sẽ áp dụng một đối tượng Pool
từ thư viện multiprocessing
. Giải pháp đơn giản và an toàn này rất dễ áp dụng chỉ với 2 dòng mã bổ sung
Chúng ta sẽ chỉ lấy mã từ phần trước, thêm nhóm quy trình và sử dụng hàm map
của nhóm thay cho hàm mặc định của Python như trong phần trước
Thật tuyệt vời khi chúng ta có thể chạy song song chức năng của mình chỉ với 2 dòng mã bổ sung phải không?
Hàm Pool.map
thực hiện chính xác như hàm bản đồ mặc định của Python. nó thực hiện tất cả các chức năng và chỉ khi đó bạn mới có thể truy cập kết quả. Bạn có thể thấy điều này bởi thực tế là tất cả các kết quả được in trên 1. 873 giây. Sự khác biệt lớn là nó chạy chức năng song song. nó thực thi 12 lời gọi hàm cùng một lúc, giảm thời gian thực hiện gấp 4 lần xuống dưới 2 giây
Khi nào thì sử dụng cái này?
Giống như phương pháp # 2, kết quả bị chặn [không thể truy cập] cho đến khi tất cả các chức năng hoàn thành. Vì tất cả chúng đều chạy song song nên chúng ta chỉ phải chờ 2 giây thay vì 8. Tuy nhiên, chúng tôi không thể thực sự lặp lại các kết quả như trong #1, vì vậy phương pháp này phù hợp để xử lý các lô như trong #2
Môi trường ảo dành cho người mới bắt đầu — nó là gì và cách tạo [+ ví dụ]
Đi sâu vào môi trường ảo Python, pip và tránh các phụ thuộc vướng víu
hướng tới khoa học dữ liệu. com
4. Đa xử lý với một iterator
Trong phần trước, chúng tôi đã sử dụng chức năng map
nhưng có những lựa chọn thay thế. Trong phần này, chúng ta sẽ kiểm tra
with Pool[processes=2] as mp_pool:
.. rest of the code
1. Hàm này gần giống như vậy nhưng thay vì chặn cho đến khi tất cả các lệnh gọi hàm hoàn tất, nó trả về một trình vòng lặp có thể truy cập ngay sau khi một lệnh gọi kết thúcNhư bạn thấy, mã này gần giống hệt như trong phần trước, ngoại trừ chúng tôi đã thay đổi map
thành
with Pool[processes=2] as mp_pool:
.. rest of the code
1. Tuy nhiên, việc thêm một chữ cái này có một số tác động đến kết quảLưu ý rằng một số chức năng kết thúc sớm hơn những chức năng khác hiện tạiSự khác biệt là nhỏ nhưng đáng chú ý. thời gian thực hiện các hàm không giống nhau cho mỗi lần gọi hàm như phần trước. Hàm
with Pool[processes=2] as mp_pool:
.. rest of the code
1 bắt đầu song song mỗi cuộc gọi; . Sau đó, nó trả về từng kết quả theo thứ tự ngay khi chúng sẵn sàng. Đó là lý do tại sao một số cuộc gọi kết thúc rất gần sau cuộc gọi khác và những cuộc gọi khác mất nhiều thời gian hơn. Theo nghĩa này, with Pool[processes=2] as mp_pool:
.. rest of the code
1 giống với cách Python 'bình thường' để thực thi một hàm như trong #1Khi nào thì sử dụng cái này?
Khi nhiều khách hàng gửi một hình ảnh mà chúng tôi phải xử lý, bây giờ chúng tôi có thể làm như vậy song song với chức năng
with Pool[processes=2] as mp_pool:
.. rest of the code
1. Hãy nghĩ về chức năng này như một phiên bản song song của #1; Docker dành cho người mới bắt đầu — Docker là gì và cách sử dụng nó [+ ví dụ]
Quản lý cơ sở hạ tầng của bạn giống như cách bạn quản lý các ứng dụng của mình
hướng tới khoa học dữ liệu. com
5. Đa xử lý với một trình vòng lặp bỏ qua thứ tự đầu vào
Phương pháp cuối cùng là
with Pool[processes=2] as mp_pool:
.. rest of the code
7. Cuộc gọi gần như giống hệt nhauMột lần nữa cuộc gọi này gần giống với phần trước;
Lưu ý rằng thứ tự của hình ảnh đã thay đổi? . 6 giâyChúng tôi vẫn hoàn thành dưới 2 giây nhưng thứ tự hoàn thành đã khác nhiều. Lưu ý rằng
with Pool[processes=2] as mp_pool:
.. rest of the code
8 được trả lại trước. Điều này không có gì đáng ngạc nhiên vì hình ảnh này nhỏ hơn nhiều. Nó không phải đợi các lệnh gọi hàm khác xảy ra chậm hơn. Phân tích đầu ra này, bạn thậm chí có thể nhận thấy rằng tôi đã lười biếng và sao chép hình ảnh đầu vào của chúng tôiKhi nào thì sử dụng cái này?
Chức năng này là phiên bản nâng cấp của #1 và #4. nó giống như một vòng lặp for bình thường nhưng nó thực thi song song tất cả các chức năng và cho phép bạn truy cập vào kết quả ngay khi bất kỳ chức năng nào sẵn sàng. Với chức năng này, khách hàng có hình ảnh nhỏ không phải đợi hình ảnh lớn hoàn thành trước khi nhận kết quả
Phát hiện chuyển động với OpenCV — phân tích hình ảnh cho người mới bắt đầu
Cách phát hiện và phân tích đối tượng chuyển động với OpenCV
hướng tới khoa học dữ liệu. com
Giới hạn số lượng quy trình/lõi
Rất dễ dàng để giới hạn số lượng quy trình/lõi/CPU tối đa mà Nhóm sẽ cho phép tại bất kỳ thời điểm nào. chỉ cần thêm đối số quy trình khi bạn khởi tạo Nhóm như bên dưới
with Pool[processes=2] as mp_pool:
.. rest of the code
Phần kết luận
Việc thêm nhiều quy trình để làm cho mã của chúng tôi chạy song song không khó; . Tóm tắt. đối tượng Pool của thư viện đa xử lý cung cấp ba chức năng. map
` là phiên bản song song của map
tích hợp sẵn của Python. Hàm
with Pool[processes=2] as mp_pool:
.. rest of the code
1 trả về một trình vòng lặp có thứ tự, việc truy cập kết quả đang bị chặn. Hàm with Pool[processes=2] as mp_pool:
.. rest of the code
7 trả về một trình vòng lặp không có thứ tự; Tôi hy vọng bài viết này rõ ràng như tôi hy vọng nhưng nếu đây không phải là trường hợp, vui lòng cho tôi biết tôi có thể làm gì để làm rõ thêm. Trong thời gian chờ đợi, hãy xem các bài viết khác của tôi về tất cả các loại chủ đề liên quan đến lập trình như thế này