Khi nào tôi nên sử dụng đa xử lý trong Python?

Một phù thủy khôn ngoan và mạnh mẽ sống trong một ngôi làng nhỏ ở giữa hư không. Hãy gọi anh ấy là Dumbledalf. Anh ấy không chỉ khôn ngoan và mạnh mẽ, mà anh ấy còn sẵn lòng giúp đỡ bất cứ ai yêu cầu và điều này có nghĩa là mọi người từ xa đến để nhờ phù thủy giúp đỡ. Câu chuyện của chúng ta bắt đầu khi vào một ngày đẹp trời, một du khách trẻ tuổi mang đến cho thầy phù thủy một cuộn giấy ma thuật. Người du hành không biết cuộn giấy chứa gì, nhưng anh ta biết rằng nếu ai đó có thể giải mã được bí mật của cuộn giấy, thì đó chính là phù thủy vĩ đại Dumbledalf.

Chương 1. Đơn luồng, đơn xử lý

Nếu bạn chưa đoán ra, thì phép loại suy khá ngớ ngẩn của tôi đang nói về CPU và các chức năng của nó. Trình hướng dẫn của chúng tôi là CPU và cuộn phép thuật là danh sách các URL dẫn đến sức mạnh của Python và kiến ​​thức để sử dụng sức mạnh đó

Ý nghĩ đầu tiên của thầy phù thủy, sau khi giải mã cuộn giấy mà không gặp quá nhiều khó khăn, là cử người bạn đáng tin cậy của mình [Haragorn? Tôi biết, tôi biết, điều đó thật tồi tệ] đến từng địa điểm trong cuộn giấy để xem và mang về những gì anh ta có thể tìm thấy

Như bạn có thể thấy, chúng tôi chỉ đơn giản lướt qua từng URL một bằng cách sử dụng for loop và đọc phản hồi. Nhờ có %%time phép thuật từ IPython, chúng ta có thể thấy rằng nó mất khoảng 12 giây với mạng internet tệ hại của tôi

chương 2. đa luồng

Trí tuệ của thầy phù thủy nổi tiếng khắp đất nước không phải vô cớ, và ông nhanh chóng nghĩ ra một phương pháp hiệu quả hơn nhiều. Thay vì cử một người đến từng địa điểm theo thứ tự, tại sao không tập hợp một nhóm người [đáng tin cậy] và cử họ riêng biệt đến từng địa điểm cùng một lúc. Trình hướng dẫn có thể chỉ cần kết hợp mọi thứ họ mang theo sau khi tất cả họ quay lại

Đúng vậy, thay vì duyệt từng danh sách một, chúng ta có thể sử dụng multithreading để truy cập nhiều URL cùng một lúc

Tốt hơn nhiều. Gần giống như. ma thuật. Sử dụng nhiều luồng có thể tăng tốc đáng kể nhiều tác vụ bị ràng buộc IO. Ở đây, phần lớn thời gian để đọc các URL là do độ trễ của mạng. Các chương trình liên kết với IO dành phần lớn thời gian để chờ đợi, bạn đoán nó, đầu vào/đầu ra [Tương tự như cách trình hướng dẫn cần đợi bạn bè/bạn bè của mình đi đến các vị trí được cung cấp trong cuộn và quay lại]. Đây có thể là I/O từ mạng, cơ sở dữ liệu, tệp hoặc thậm chí là người dùng. I/O này có xu hướng mất một lượng thời gian đáng kể, vì bản thân nguồn có thể cần thực hiện quá trình xử lý của chính nó trước khi chuyển qua I/O. Ví dụ: CPU hoạt động nhanh hơn rất nhiều so với kết nối mạng có thể truyền dữ liệu [Hãy nghĩ về Flash so với bà của bạn]

Ghi chú. Multithreading có thể rất hữu ích trong các nhiệm vụ như quét web

Chương 3. đa xử lý

Khi năm tháng trôi qua và danh tiếng của phù thủy của chúng ta ngày càng tăng, thì sự ghen tị của một phù thủy hắc ám khá khó chịu [Sarudort? Voldeman?]. Được trang bị với sự xảo quyệt quỷ quyệt và bị thúc đẩy bởi sự ghen tị, phù thủy hắc ám đã thực hiện một lời nguyền khủng khiếp đối với Dumbledalf. Ngay sau khi lời nguyền hóa giải, Dumbledalf biết rằng ông chỉ có vài phút để phá vỡ nó. Xé nát cuốn sách thần chú của mình trong tuyệt vọng, anh ta tìm thấy một câu thần chú phản đòn có vẻ như nó có thể làm được điều đó. Vấn đề duy nhất là nó yêu cầu anh ta tính tổng của tất cả các số nguyên tố dưới 1000000. Câu thần chú kỳ lạ, nhưng nó là như vậy

Giờ đây, thuật sĩ biết rằng việc tính toán giá trị sẽ trở nên tầm thường nếu có đủ thời gian nhưng thời gian không phải là thứ xa xỉ mà anh ta có. Mặc dù anh ta là một phù thủy, ngay cả khi anh ta bị giới hạn bởi con người của mình và anh ta chỉ có thể tính toán một con số tại một thời điểm. Nếu anh ta tính tổng từng số nguyên tố thì sẽ mất rất nhiều thời gian. Chỉ còn vài giây để đảo ngược lời nguyền, anh ấy đột nhiên nhớ lại câu thần chú multiprocessing mà anh ấy đã học được từ cuộn ma thuật nhiều năm trước. Câu thần chú này sẽ cho phép anh ta tạo các bản sao của chính mình và việc chia nhỏ các số giữa các bản sao của anh ta sẽ cho phép anh ta kiểm tra xem nhiều số có phải là số nguyên tố cùng một lúc hay không. Cuối cùng, tất cả những gì anh ta phải làm là cộng tất cả các số nguyên tố mà anh ta và các bản sao của mình khám phá ra

Với CPU hiện đại thường có nhiều hơn một lõi, chúng ta có thể tăng tốc các tác vụ liên quan đến CPU bằng cách sử dụng mô-đun multiprocessing. Các tác vụ ràng buộc CPU là các chương trình dành phần lớn thời gian để thực hiện các phép tính trong CPU [tính toán toán học, xử lý hình ảnh, v.v. ]. Nếu các phép tính có thể được thực hiện độc lập với nhau, chúng ta có thể chia chúng ra giữa các lõi CPU có sẵn, do đó đạt được tốc độ xử lý tăng đáng kể

Tât cả nhưng điêu bạn phải lam la;

  1. Xác định chức năng được áp dụng
  2. Chuẩn bị một danh sách các mục mà chức năng sẽ được áp dụng trên
  3. Quá trình sinh sản bằng cách sử dụng multiprocessing.Pool. Số được chuyển đến Pool[] sẽ là số quy trình được sinh ra. Nhúng vào bên trong câu lệnh with đảm bảo rằng các quy trình bị hủy sau khi thực hiện xong
  4. Kết hợp các đầu ra bằng cách sử dụng chức năng map của quy trình Nhóm. Đầu vào cho hàm map là hàm được áp dụng cho từng mục và danh sách các mục

Ghi chú. Chức năng có thể được xác định để thực hiện bất kỳ nhiệm vụ nào có thể được thực hiện song song. Ví dụ: hàm có thể chứa mã để ghi kết quả tính toán vào tệp

Vì vậy, tại sao chúng ta cần tách biệt multiprocessingmultithreading? . Dị giáo. Hãy xem tại sao điều này xảy ra

Giống như thuật sĩ bị giới hạn bởi bản chất con người của anh ta và chỉ có thể tính toán một số tại một thời điểm, Python đi kèm với một thứ gọi là Khóa thông dịch viên toàn cầu [GIL]. Python sẽ vui vẻ cho phép bạn sinh ra bao nhiêu %%time4 tùy thích, nhưng GIL đảm bảo rằng chỉ một trong số những %%time4 đó sẽ được thực thi tại bất kỳ thời điểm nào

Đối với một nhiệm vụ giới hạn IO, điều đó hoàn toàn ổn. Một %%time6 kích hoạt một yêu cầu tới một URL và trong khi chờ phản hồi, %%time6 đó có thể được đổi chỗ cho một %%time6 khác kích hoạt một yêu cầu khác tới một URL khác. Vì một %%time6 không phải làm bất cứ điều gì cho đến khi nó nhận được phản hồi, nên việc chỉ một %%time6 đang thực thi tại một thời điểm nhất định không thực sự quan trọng

Đối với một tác vụ liên quan đến CPU, việc có nhiều %%time4 cũng hữu ích như núm vú trên tấm che ngực. Bởi vì mỗi lần chỉ có một %%time6 được thực thi, ngay cả khi bạn sinh ra nhiều %%time4 với mỗi cái có số riêng để kiểm tra tính nguyên tố, CPU vẫn sẽ chỉ xử lý một %%time6 tại một thời điểm. Trên thực tế, các con số vẫn sẽ được kiểm tra lần lượt. Chi phí chung trong việc xử lý nhiều %%time4 sẽ góp phần làm giảm hiệu suất mà bạn có thể quan sát thấy nếu bạn sử dụng multithreading trong một tác vụ ràng buộc với CPU

Để khắc phục 'giới hạn' này, chúng tôi sử dụng mô-đun multiprocessing. Thay vì sử dụng %%time4, multiprocessing sử dụng, tốt, nhiều Multithreading0. Mỗi Multithreading1 có trình thông dịch và không gian bộ nhớ riêng, vì vậy GIL sẽ không giữ lại mọi thứ. Về bản chất, mỗi Multithreading1 sử dụng một lõi CPU khác nhau để hoạt động trên một số lượng khác nhau, tại cùng một thời điểm. Ngọt

Bạn có thể nhận thấy rằng mức sử dụng CPU tăng cao hơn nhiều khi bạn đang sử dụng multiprocessing so với khi sử dụng một vòng lặp for đơn giản, hoặc thậm chí là multithreading. Đó là bởi vì chương trình của bạn đang sử dụng nhiều lõi CPU, thay vì chỉ một lõi. Đây là một điều tốt

Hãy nhớ rằng multiprocessing đi kèm với tổng chi phí riêng để quản lý nhiều Multithreading0, thường có xu hướng nặng hơn chi phí multithreading. [ Multithreading8 sinh ra một trình thông dịch riêng biệt và chỉ định một không gian bộ nhớ riêng cho mỗi Multithreading1, vì vậy duh. ]. Điều này có nghĩa là, theo nguyên tắc thông thường, tốt hơn là sử dụng multithreading nhẹ khi bạn có thể thoát khỏi nó [đọc. nhiệm vụ ràng buộc IO]. Khi quá trình xử lý CPU trở thành nút cổ chai của bạn, thông thường đã đến lúc triệu hồi mô-đun multiprocessing. Nhưng hãy nhớ rằng, sức mạnh lớn đi kèm với trách nhiệm lớn

Nếu bạn sinh ra nhiều Multithreading0 hơn mức CPU của bạn có thể xử lý tại một thời điểm, bạn sẽ nhận thấy hiệu suất của mình bắt đầu giảm xuống. Điều này là do hệ điều hành hiện phải thực hiện nhiều công việc hơn khi hoán đổi Multithreading0 trong và ngoài lõi CPU vì bạn có nhiều Multithreading0 hơn lõi. Thực tế có thể phức tạp hơn một lời giải thích đơn giản, nhưng đó là ý tưởng cơ bản. Bạn có thể thấy hiệu suất giảm trên hệ thống của tôi khi chúng tôi đạt 16 Multithreading0. Điều này là do CPU của tôi chỉ có 16 lõi logic

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

Đa xử lý [sơ đồ bên phải] nhân một bộ xử lý đơn lẻ — sao chép mã, dữ liệu và tệp, điều này phát sinh nhiều chi phí hơn. Đa luồng hữu ích cho các quy trình liên kết với IO, chẳng hạn như đọc tệp từ mạng hoặc cơ sở dữ liệu vì mỗi luồng có thể chạy đồng thời quy trình liên kết với IO .

Khi nào bạn sẽ sử dụng nhóm đa xử lý?

Sử dụng nhóm đa xử lý nếu tác vụ của bạn độc lập . Điều này có nghĩa là mỗi tác vụ không phụ thuộc vào các tác vụ khác có thể thực thi cùng lúc. Nó cũng có thể có nghĩa là các tác vụ không phụ thuộc vào bất kỳ dữ liệu nào ngoài dữ liệu được cung cấp thông qua các đối số chức năng cho tác vụ.

Cái nào tốt hơn trong đa xử lý hoặc đa luồng của Python?

Python đa xử lý dễ thả vào hơn phân luồng nhưng có chi phí bộ nhớ cao hơn. Nếu mã của bạn bị ràng buộc bởi CPU, đa xử lý rất có thể sẽ là lựa chọn tốt hơn —đặc biệt nếu máy đích có nhiều lõi hoặc nhiều CPU.

Có nên sử dụng đa luồng để tăng tốc mã Python của bạn không?

Đa luồng cho phép bạn viết theo cách mà nhiều hoạt động có thể tiến hành đồng thời trong cùng một chương trình. Python không cho phép đa luồng, nhưng nếu bạn muốn chạy chương trình của mình với tốc độ cần đợi thứ gì đó như IO, thì nó được sử dụng rất nhiều

Chủ Đề