Phần tìm hiểu sâu này về các thư viện song song hóa Python - đa xử lý và phân luồng - sẽ giải thích nên sử dụng cái nào khi nào đối với các bộ vấn đề khác nhau của nhà khoa học dữ liệu Show
Ngày 7 tháng 9 năm 2019 • 14 phút đọc Sớm hay muộn, mọi dự án khoa học dữ liệu đều phải đối mặt với thách thức không thể tránh khỏi. tốc độ, vận tốc. Làm việc với các tập dữ liệu lớn hơn dẫn đến việc xử lý chúng chậm hơn, do đó, cuối cùng bạn sẽ phải suy nghĩ về việc tối ưu hóa thời gian chạy thuật toán của mình. Như hầu hết các bạn đã biết, song song hóa là một bước cần thiết của quá trình tối ưu hóa này. Python cung cấp hai thư viện tích hợp để song song hóa. đa xử lý và phân luồng. Trong bài viết này, chúng ta sẽ khám phá cách các nhà khoa học dữ liệu có thể lựa chọn giữa hai phương pháp và những yếu tố nào cần được lưu ý khi làm như vậy Điện toán song song và Khoa học dữ liệuNhư các bạn đã biết, khoa học dữ liệu là khoa học xử lý lượng lớn dữ liệu và trích xuất những hiểu biết hữu ích từ chúng. Thông thường, các thao tác chúng tôi thực hiện trên dữ liệu có thể dễ dàng song song hóa, nghĩa là các tác nhân xử lý khác nhau có thể chạy thao tác trên dữ liệu từng phần một, sau đó kết hợp các kết quả ở cuối để có được kết quả hoàn chỉnh Để hình dung rõ hơn về khả năng song song hóa, hãy xem xét một phép loại suy trong thế giới thực. Giả sử bạn cần dọn ba phòng trong nhà. Bạn có thể tự làm tất cả, lần lượt dọn phòng hoặc bạn có thể nhờ hai anh chị em của mình giúp bạn, mỗi người dọn một phòng. Trong cách tiếp cận thứ hai, mỗi bạn đang làm việc song song trên một phần của toàn bộ nhiệm vụ, do đó giảm tổng thời gian cần thiết để hoàn thành nó. Đây là tính song song trong hành động Xử lý song song có thể đạt được trong Python theo hai cách khác nhau. đa xử lý và phân luồng Đa xử lý và phân luồng. Học thuyếtVề cơ bản, đa xử lý và phân luồng là hai cách để đạt được tính toán song song, sử dụng các quy trình và luồng tương ứng làm tác nhân xử lý. Để hiểu cách thức hoạt động của chúng, chúng ta phải làm rõ quy trình và luồng là gì Quá trìnhMột tiến trình là một thể hiện của một chương trình máy tính đang được thực thi. Mỗi quy trình có không gian bộ nhớ riêng mà nó sử dụng để lưu trữ các lệnh đang được chạy, cũng như bất kỳ dữ liệu nào nó cần lưu trữ và truy cập để thực thi chủ đềChủ đề là các thành phần của một quá trình, có thể chạy song song. Có thể có nhiều luồng trong một tiến trình và chúng chia sẻ cùng một không gian bộ nhớ, tôi. e. không gian bộ nhớ của tiến trình cha. Điều này có nghĩa là mã được thực thi cũng như tất cả các biến được khai báo trong chương trình sẽ được chia sẻ bởi tất cả các luồng Quy trình và Chủ đề, Bởi I, Cburnett, CC BY-SA 3. 0, Liên kết Ví dụ: chúng ta hãy xem xét các chương trình đang chạy trên máy tính của bạn ngay bây giờ. Có thể bạn đang đọc bài viết này trên một trình duyệt có nhiều tab đang mở. Bạn cũng có thể đang nghe nhạc qua ứng dụng Spotify trên máy tính cùng lúc. Trình duyệt và ứng dụng Spotify là các quy trình khác nhau; . Các tab khác nhau trong trình duyệt của bạn có thể được chạy trong các luồng khác nhau. Spotify có thể phát nhạc trong một luồng, tải nhạc từ internet ở một luồng khác và sử dụng luồng thứ ba để hiển thị GUI. Điều này sẽ được gọi là đa luồng. Điều tương tự cũng có thể được thực hiện với đa xử lý—nhiều quy trình—cũng vậy. Trên thực tế, hầu hết các trình duyệt hiện đại như Chrome và Firefox đều sử dụng đa xử lý chứ không phải đa luồng để xử lý nhiều tab chi tiết kỹ thuật
Cạm bẫy của tính toán song songGiới thiệu tính song song cho một chương trình không phải lúc nào cũng là một trò chơi có tổng dương; . Những cái quan trọng nhất như sau
Đa xử lý và phân luồng trong PythonKhóa phiên dịch viên toàn cầuKhi nói đến Python, có một số điều kỳ lạ cần lưu ý. Chúng tôi biết rằng các luồng chia sẻ cùng một không gian bộ nhớ, vì vậy phải thực hiện các biện pháp phòng ngừa đặc biệt để hai luồng không ghi vào cùng một vị trí bộ nhớ. Trình thông dịch CPython xử lý việc này bằng cơ chế có tên là 8 hoặc Khóa thông dịch viên toàn cầuTừ wiki Python
Kiểm tra các trang trình bày ở đây để có cái nhìn chi tiết hơn về Python 8 8 hoàn thành công việc của mình, nhưng phải trả giá. Nó tuần tự hóa hiệu quả các hướng dẫn ở cấp độ thông dịch viên. Cách thức hoạt động của nó như sau. để bất kỳ luồng nào thực hiện bất kỳ chức năng nào, nó phải có khóa toàn cục. Chỉ một luồng duy nhất có thể có được khóa đó tại một thời điểm, điều đó có nghĩa là trình thông dịch cuối cùng sẽ chạy các hướng dẫn một cách an toàn. Thiết kế này làm cho luồng quản lý bộ nhớ trở nên an toàn, nhưng do đó, nó không thể sử dụng nhiều lõi CPU. Trong CPU lõi đơn, đó là điều mà các nhà thiết kế đã nghĩ đến khi phát triển CPython, đó không phải là vấn đề lớn. Nhưng khóa toàn cầu này cuối cùng lại trở thành một nút cổ chai nếu bạn đang sử dụng CPU đa lõiTuy nhiên, nút cổ chai này trở nên không liên quan nếu chương trình của bạn có nút cổ chai nghiêm trọng hơn ở nơi khác, chẳng hạn như trong mạng, IO hoặc tương tác người dùng. Trong những trường hợp đó, luồng là một phương pháp song song hoàn toàn hiệu quả. Nhưng đối với các chương trình bị ràng buộc bởi CPU, luồng kết thúc khiến chương trình chậm hơn. Hãy khám phá điều này với một số trường hợp sử dụng ví dụ Các trường hợp sử dụng cho ThreadingCác chương trình GUI luôn sử dụng luồng để làm cho các ứng dụng phản hồi nhanh. Ví dụ: trong một chương trình soạn thảo văn bản, một luồng có thể đảm nhiệm việc ghi lại các đầu vào của người dùng, một luồng khác có thể chịu trách nhiệm hiển thị văn bản, luồng thứ ba có thể kiểm tra chính tả, v.v. Ở đây, chương trình phải chờ tương tác của người dùng, đây là điểm nghẽn lớn nhất. Sử dụng đa xử lý sẽ không làm cho chương trình nhanh hơn Một trường hợp sử dụng khác cho phân luồng là các chương trình bị ràng buộc IO hoặc bị ràng buộc mạng, chẳng hạn như trình quét web. Trong trường hợp này, nhiều luồng có thể xử lý song song nhiều trang web. Các luồng phải tải xuống các trang web từ Internet và đó sẽ là nút cổ chai lớn nhất, vì vậy luồng là một giải pháp hoàn hảo ở đây. Các máy chủ web, bị ràng buộc bởi mạng, hoạt động tương tự; . Một ví dụ liên quan khác là Tensorflow, sử dụng nhóm luồng để chuyển đổi dữ liệu song song Các trường hợp sử dụng cho đa xử lýĐa xử lý vượt trội hơn luồng trong trường hợp chương trình sử dụng nhiều CPU và không phải thực hiện bất kỳ tương tác IO hoặc người dùng nào. Ví dụ: bất kỳ chương trình nào chỉ xử lý các con số sẽ thấy sự tăng tốc đáng kể từ đa xử lý; . Một ví dụ thú vị trong thế giới thực là Pytorch Dataloader, sử dụng nhiều quy trình con để tải dữ liệu vào GPU Song song hóa trong Python, trong hành độngPython cung cấp hai thư viện - 0 và 1- cho các phương thức song song hóa cùng tên. Bất chấp sự khác biệt cơ bản giữa chúng, hai thư viện cung cấp API rất giống nhau (kể từ Python 3. 7). Hãy xem chúng hoạt động
Bạn có thể thấy rằng tôi đã tạo một hàm 2 để tạo một danh sách các số ngẫu nhiên và sau đó nhân tất cả các phần tử của nó một cách tuần tự. Đây có thể là một quy trình khá nặng nề nếu số lượng mặt hàng đủ lớn, chẳng hạn như 50k hoặc 100kSau đó, tôi đã tạo hai luồng sẽ thực hiện cùng một chức năng. Các đối tượng luồng có phương thức 3 khởi động luồng không đồng bộ. Nếu chúng ta muốn đợi chúng kết thúc và quay trở lại, chúng ta phải gọi phương thức 4, và đó là những gì chúng ta đã làm ở trênNhư bạn có thể thấy, API để tạo một luồng mới cho một tác vụ ở chế độ nền khá đơn giản. Điều tuyệt vời là API dành cho đa xử lý cũng gần như giống hệt nhau;
Nó đây rồi—chỉ cần tráo đổi 5 với 6 và bạn có cùng một chương trình được triển khai bằng cách sử dụng đa xử lýRõ ràng là còn rất nhiều điều bạn có thể làm với điều này, nhưng điều đó không nằm trong phạm vi của bài viết này, vì vậy chúng tôi sẽ không đi sâu vào vấn đề này ở đây. Kiểm tra các tài liệu ở đây và ở đây nếu bạn muốn tìm hiểu thêm điểm chuẩnBây giờ chúng ta đã có ý tưởng về cách mã triển khai song song hóa trông như thế nào, hãy quay lại các vấn đề về hiệu suất. Như chúng tôi đã lưu ý trước đây, phân luồng không phù hợp với các tác vụ bị ràng buộc bởi CPU; . Chúng tôi có thể xác thực điều này bằng một số điểm chuẩn đơn giản Đầu tiên, hãy xem phân luồng so sánh với đa xử lý như thế nào đối với mẫu mã mà tôi đã chỉ cho bạn ở trên. Hãy nhớ rằng tác vụ này không liên quan đến bất kỳ loại IO nào, vì vậy đây là tác vụ thuần túy ràng buộc với CPU Và hãy xem điểm chuẩn tương tự cho tác vụ bị ràng buộc IO. Ví dụ: chức năng sau -
Chức năng này chỉ đơn giản là tìm nạp một trang web và lưu nó vào một tệp cục bộ, nhiều lần trong một vòng lặp. Vô dụng nhưng đơn giản và do đó rất phù hợp để trình diễn. Hãy nhìn vào điểm chuẩn Bây giờ có một số điều cần lưu ý từ hai biểu đồ này
Từ tất cả các cuộc thảo luận này, chúng ta có thể kết luận như sau -
Một quy trình xử lý dữ liệu điển hình có thể được chia thành các bước sau
Hãy khám phá cách chúng tôi có thể giới thiệu tính song song trong các tác vụ này để chúng có thể được tăng tốc Bước 1 liên quan đến việc đọc dữ liệu từ đĩa, vì vậy rõ ràng đĩa IO sẽ là nút cổ chai cho bước này. Như chúng ta đã thảo luận, các luồng là lựa chọn tốt nhất để song song hóa loại hoạt động này. Tương tự, bước 3 cũng là một ứng cử viên lý tưởng cho việc giới thiệu phân luồng Tuy nhiên, bước 2 bao gồm các tính toán liên quan đến CPU hoặc GPU. Nếu đó là một tác vụ dựa trên CPU, việc sử dụng phân luồng sẽ không có ích gì; . Chỉ sau đó, chúng tôi mới có thể khai thác nhiều lõi của CPU và đạt được tính song song. Nếu đó là tác vụ dựa trên GPU, vì GPU đã triển khai kiến trúc song song lớn ở cấp độ phần cứng, nên việc sử dụng đúng giao diện (thư viện và trình điều khiển) để tương tác với GPU sẽ đảm nhận phần còn lại Bây giờ bạn có thể đang nghĩ, “Đường dẫn dữ liệu của tôi trông hơi khác so với cái này; . ” Tuy nhiên, bạn sẽ có thể quan sát phương pháp được sử dụng ở đây để quyết định giữa phân luồng và đa xử lý. Các yếu tố bạn nên xem xét là
Với những yếu tố này, cùng với những điều rút ra ở trên, bạn sẽ có thể đưa ra quyết định. Ngoài ra, hãy nhớ rằng bạn không phải sử dụng một dạng song song duy nhất trong suốt chương trình của mình. Bạn nên sử dụng cái này hay cái kia cho các phần khác nhau trong chương trình của mình, tùy theo phần nào phù hợp với phần cụ thể đó Bây giờ chúng ta sẽ xem xét hai tình huống ví dụ mà một nhà khoa học dữ liệu có thể gặp phải và cách bạn có thể sử dụng điện toán song song để tăng tốc chúng Kịch bản. Tải xuống emailGiả sử bạn muốn phân tích tất cả các email trong hộp thư đến của công ty khởi nghiệp do chính bạn phát triển và hiểu xu hướng. ai là người gửi thường xuyên nhất, từ khóa phổ biến nhất xuất hiện trong email là gì, ngày nào trong tuần hoặc giờ nào trong ngày bạn nhận được nhiều email nhất, v.v. Tất nhiên, bước đầu tiên của dự án này sẽ là tải email xuống máy tính của bạn Lúc đầu, hãy thực hiện tuần tự mà không sử dụng bất kỳ phép song song nào. Mã để sử dụng ở bên dưới và nó sẽ khá dễ hiểu. Có một chức năng 8 lấy danh sách id email làm đầu vào và tải chúng xuống một cách tuần tự. Điều này gọi chức năng này với danh sách id của 100 email cùng một lúc 2Mất thời gian. 9 giâyBây giờ, hãy giới thiệu một số khả năng song song hóa vào tác vụ này để tăng tốc mọi thứ. Trước khi đi sâu vào viết mã, chúng ta phải quyết định giữa phân luồng và đa xử lý. Như bạn đã học cho đến nay, luồng là lựa chọn tốt nhất khi nói đến các tác vụ có một số IO làm nút cổ chai. Nhiệm vụ hiện tại rõ ràng thuộc về danh mục này, vì nó đang truy cập máy chủ IMAP qua internet. Vì vậy, chúng tôi sẽ đi với 0Phần lớn mã chúng ta sẽ sử dụng sẽ giống với mã chúng ta đã sử dụng trong trường hợp tuần tự. Sự khác biệt duy nhất là chúng tôi sẽ chia danh sách 100 id email thành 10 phần nhỏ hơn, mỗi phần chứa 10 id, sau đó tạo 10 chuỗi và gọi hàm 8 với một phần khác với mỗi chuỗi. Tôi đang sử dụng lớp 2 từ thư viện chuẩn Python để phân luồng 7Mất thời gian. 3 giâyNhư bạn có thể thấy, phân luồng, tăng tốc đáng kể Kịch bản. Phân loại bằng Scikit-LearnGiả sử bạn gặp sự cố phân loại và bạn muốn sử dụng trình phân loại rừng ngẫu nhiên cho việc này. Vì đây là một thuật toán học máy tiêu chuẩn và nổi tiếng, chúng ta đừng phát minh lại bánh xe và chỉ sử dụng 4Đoạn mã dưới đây phục vụ mục đích trình diễn. Tôi đã tạo một tập dữ liệu phân loại bằng cách sử dụng hàm trợ giúp 5, sau đó đào tạo một 6 về điều đó. Ngoài ra, tôi đang định thời gian cho phần mã thực hiện công việc cốt lõi là điều chỉnh mô hình 2Mất thời gian. 7 giâyBây giờ chúng ta sẽ xem xét cách chúng ta có thể giảm thời gian chạy của thuật toán này. Chúng tôi biết rằng thuật toán này có thể được song song hóa ở một mức độ nào đó, nhưng loại song song hóa nào sẽ phù hợp? . Vì vậy, đa xử lý sẽ là sự lựa chọn hợp lý May mắn thay, 8 đã triển khai đa xử lý vào thuật toán này và chúng tôi sẽ không phải viết lại từ đầu. Như bạn có thể thấy trong đoạn mã bên dưới, chúng tôi chỉ cần cung cấp một tham số 9—số lượng quy trình mà nó sẽ sử dụng—để kích hoạt tính năng đa xử lý 6Mất thời gian. 20 giâyNhư mong đợi, đa xử lý làm cho nó nhanh hơn một chút Sự kết luậnHầu hết nếu không muốn nói là tất cả các dự án khoa học dữ liệu sẽ thấy tốc độ tăng mạnh với điện toán song song. Trên thực tế, nhiều thư viện khoa học dữ liệu phổ biến đã tích hợp tính song song, bạn chỉ cần kích hoạt nó. Vì vậy, trước khi tự mình thử triển khai nó, hãy xem qua tài liệu của thư viện bạn đang sử dụng và kiểm tra xem nó có hỗ trợ xử lý song song hay không (nhân tiện, tôi chắc chắn khuyên bạn nên kiểm tra dask). Trong trường hợp không, bài viết này sẽ hỗ trợ bạn tự thực hiện Sẵn sàng để xây dựng, đào tạo và triển khai AI?Bắt đầu miễn phí với nền tảng AI hợp tác của FloydHubDùng thử FloydHub miễn phíThông tin về các Tác giả Sumit là một người đam mê máy tính và bắt đầu lập trình từ khi còn nhỏ; . Bất cứ khi nào anh ấy không lập trình, bạn có thể thấy anh ấy đọc triết học, chơi ghi-ta, chụp ảnh hoặc viết blog. Bạn có thể kết nối với Sumit trên Twitter, LinkedIn, Github và trang web của anh ấy Đa luồng hoạt động như thế nào trong Python với GIL?GIL chỉ cho phép một chuỗi hệ điều hành thực thi mã byte Python tại bất kỳ thời điểm nào và hậu quả của điều này là không thể tăng tốc mã Python sử dụng nhiều CPU bằng cách phân phối . Tuy nhiên, đây không phải là tác động tiêu cực duy nhất của GIL.
Đa luồng Python có sử dụng nhiều lõi không?Các quy trình Python thường sử dụng một luồng đơn vì GIL. Mặc dù có GIL, các thư viện thực hiện các tác vụ tính toán nặng như numpy, scipy và pytorch sử dụng triển khai dựa trên C hoàn toàn, cho phép sử dụng nhiều lõi .
Đa luồng trong Python có hiệu quả không?Đây là hai ưu điểm chính. Đa luồng trong Python hợp lý hóa việc sử dụng tài nguyên hiệu quả vì các luồng chia sẻ cùng một bộ nhớ và không gian dữ liệu. Nó cũng cho phép xuất hiện đồng thời nhiều tác vụ và giảm thời gian phản hồi.
Python có thể chạy nhiều luồng cùng một lúc không?Tóm lại, phân luồng trong Python cho phép nhiều luồng được tạo trong một quy trình duy nhất, nhưng do GIL, không có luồng nào chạy cùng một lúc. Threading is still a very good option when it comes to running multiple I/O bound tasks concurrently. |