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;
- Xác định chức năng được áp dụng
- Chuẩn bị một danh sách các mục mà chức năng sẽ được áp dụng trên
- Quá trình sinh sản bằng cách sử dụng
multiprocessing.Pool
. Số được chuyển đếnPool[]
sẽ là số quy trình được sinh ra. Nhúng vào bên trong câu lệnhwith
đảm bảo rằng các quy trình bị hủy sau khi thực hiện xong - 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àmmap
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 multiprocessing
và multithreading
? . 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 %%time
4 tùy thích, nhưng GIL đảm bảo rằng chỉ một trong số những %%time
4 đó 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 %%time
6 kích hoạt một yêu cầu tới một URL và trong khi chờ phản hồi, %%time
6 đó có thể được đổi chỗ cho một %%time
6 khác kích hoạt một yêu cầu khác tới một URL khác. Vì một %%time
6 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 %%time
6 đ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 %%time
4 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 %%time
6 được thực thi, ngay cả khi bạn sinh ra nhiều %%time
4 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 %%time
6 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 %%time
4 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 %%time
4, multiprocessing
sử dụng, tốt, nhiều Multithreading
0. Mỗi Multithreading
1 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 Multithreading
1 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 Multithreading
0, thường có xu hướng nặng hơn chi phí multithreading
. [ Multithreading
8 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 Multithreading
1, 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 Multithreading
0 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 Multithreading
0 trong và ngoài lõi CPU vì bạn có nhiều Multithreading
0 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 Multithreading
0. Điều này là do CPU của tôi chỉ có 16 lõi logic