Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.
Sử dụng đa xử lý trong Python
Trong bài viết này, bạn sẽ học cách sử dụng module multiprocessing trong Python để chạy mã đồng thời. Multiprocessing là một kỹ thuật mạnh mẽ cho phép tận dụng tối đa tài nguyên của CPU bằng cách thực hiện nhiều tác vụ đồng thời, giúp tăng hiệu suất và giảm thời gian xử lý cho các ứng dụng đòi hỏi tài nguyên cao. Hãy cùng tìm hiểu cách triển khai và sử dụng multiprocessing để xử lý các tác vụ nặng một cách hiệu quả trong Python.
Giới thiệu về đa xử lý trong Python
Thông thường, chương trình xử lý hai loại tác vụ chính:
- Tác vụ I/O-bound: Nếu một tác vụ thực hiện nhiều thao tác nhập/xuất, nó được gọi là tác vụ I/O-bound. Ví dụ điển hình của tác vụ I/O-bound là đọc từ tệp, ghi vào tệp, kết nối cơ sở dữ liệu và thực hiện yêu cầu mạng. Đối với tác vụ I/O-bound, bạn có thể sử dụng đa luồng (multithreading) để tăng tốc.
- Tác vụ CPU-bound: Khi một tác vụ thực hiện nhiều thao tác sử dụng CPU, nó được gọi là tác vụ CPU-bound. Ví dụ như tính toán số học, thay đổi kích thước ảnh và phát trực tuyến video là các tác vụ CPU-bound. Để tăng tốc chương trình với nhiều tác vụ CPU-bound, bạn sử dụng đa xử lý (multiprocessing).
Đa xử lý cho phép hai hoặc nhiều bộ xử lý xử lý đồng thời hai hoặc nhiều phần khác nhau của một chương trình.
Trong Python, bạn sử dụng module multiprocessing
để thực hiện đa xử lý.
Bài viết này được đăng tại [free tuts .net]
Ví dụ về đa xử lý trong Python
Xem chương trình sau:
import time def task(): result = 0 for _ in range(10**8): result += 1 return result if __name__ == '__main__': start = time.perf_counter() task() task() finish = time.perf_counter() print(f'It took {finish-start:.2f} second(s) to finish')
Kết quả:
It took 5.55 second(s) to finish
Giải thích cách hoạt động:
Đầu tiên, định nghĩa hàm task()
là một tác vụ CPU-bound vì nó thực hiện một phép tính nặng bằng cách lặp lại 100 triệu lần và tăng một biến result
:
def task(): result = 0 for _ in range(10**8): result += 1 return result
Thứ hai, gọi hàm task()
hai lần và ghi lại thời gian xử lý:
if __name__ == '__main__': start = time.perf_counter() task() task() finish = time.perf_counter() print(f'It took {finish-start: .2f} second(s) to finish')
Trên máy tính của chúng tôi, mất 5.55 giây để hoàn thành.
Sử dụng module multiprocessing
trong Python
Chương trình sau sử dụng module multiprocessing
nhưng mất ít thời gian hơn:
import time import multiprocessing def task() -> int: result = 0 for _ in range(10**8): result += 1 return result if __name__ == '__main__': start = time.perf_counter() p1 = multiprocessing.Process(target=task) p2 = multiprocessing.Process(target=task) p1.start() p2.start() p1.join() p2.join() finish = time.perf_counter() print(f'It took {finish-start:.2f} second(s) to finish')
Kết quả:
It took 3.43 second(s) to finish
Giải thích cách hoạt động:
Đầu tiên, nhập module multiprocessing
:
import multiprocessing
Thứ hai, tạo hai tiến trình và truyền hàm task
vào mỗi tiến trình:
p1 = multiprocessing.Process(target=task) p2 = multiprocessing.Process(target=task)
Lưu ý rằng hàm khởi tạo Process()
trả về một đối tượng Process
mới.
Thứ ba, gọi phương thức start()
của các đối tượng Process
để bắt đầu tiến trình:
p1.start() p2.start()
Cuối cùng, chờ tiến trình hoàn thành bằng cách gọi phương thức join()
:
Ví dụ thực tế về đa xử lý trong Python
Chúng ta sẽ sử dụng module multiprocessing
để thay đổi kích thước các ảnh có độ phân giải cao.
Đầu tiên, cài đặt thư viện Pillow để xử lý ảnh:
pip install Pillow
Thứ hai, phát triển một chương trình tạo thumbnail của các ảnh trong thư mục images
và lưu chúng vào thư mục thumbs
:
import time import os from PIL import Image, ImageFilter filenames = [ 'images/1.jpg', 'images/2.jpg', 'images/3.jpg', 'images/4.jpg', 'images/5.jpg', ] def create_thumbnail(filename, size=(50,50), thumb_dir ='thumbs'): # mở ảnh img = Image.open(filename) # áp dụng bộ lọc Gaussian Blur img = img.filter(ImageFilter.GaussianBlur()) # tạo thumbnail img.thumbnail(size) # lưu ảnh img.save(f'{thumb_dir}/{os.path.basename(filename)}') # hiển thị thông báo print(f'{filename} đã được xử lý...') if __name__ == '__main__': start = time.perf_counter() for filename in filenames: create_thumbnail(filename) finish = time.perf_counter() print(f'Mất {finish-start:.2f} giây để hoàn thành')
Trên máy tính của chúng tôi, mất khoảng 4.06 giây để hoàn thành:
images/1.jpg đã được xử lý... images/2.jpg đã được xử lý... images/3.jpg đã được xử lý... images/4.jpg đã được xử lý... images/5.jpg đã được xử lý... Mất 4.06 giây để hoàn thành
Thứ ba, sửa đổi chương trình để sử dụng đa xử lý. Mỗi tiến trình sẽ tạo một thumbnail cho một ảnh:
import time import os from PIL import Image, ImageFilter import multiprocessing filenames = [ 'images/1.jpg', 'images/2.jpg', 'images/3.jpg', 'images/4.jpg', 'images/5.jpg', ] def create_thumbnail(filename, size=(50,50), thumb_dir ='thumbs'): # mở ảnh img = Image.open(filename) # áp dụng bộ lọc Gaussian Blur img = img.filter(ImageFilter.GaussianBlur()) # tạo thumbnail img.thumbnail(size) # lưu ảnh img.save(f'{thumb_dir}/{os.path.basename(filename)}') # hiển thị thông báo print(f'{filename} đã được xử lý...') def main(): start = time.perf_counter() # tạo các tiến trình processes = [multiprocessing.Process(target=create_thumbnail, args=[filename]) for filename in filenames] # bắt đầu các tiến trình for process in processes: process.start() # chờ hoàn thành for process in processes: process.join() finish = time.perf_counter() print(f'Mất {finish-start:.2f} giây để hoàn thành') if __name__ == '__main__': main()
Kết quả:
images/5.jpg đã được xử lý... images/4.jpg đã được xử lý... images/1.jpg đã được xử lý... images/3.jpg đã được xử lý... images/2.jpg đã được xử lý... Mất 2.92 giây để hoàn thành
Trong trường hợp này, kết quả cho thấy chương trình đã xử lý các ảnh nhanh hơn.
Kết bài
Sử dụng module multiprocessing
trong Python để chạy mã đồng thời giúp xử lý các tác vụ CPU-bound một cách hiệu quả, tận dụng tối đa khả năng của CPU và giảm đáng kể thời gian xử lý. Bằng cách chia nhỏ các tác vụ lớn thành các quy trình nhỏ hơn và chạy chúng song song, bạn có thể cải thiện hiệu suất của ứng dụng và đạt được kết quả nhanh chóng hơn. Hãy áp dụng multiprocessing
trong các dự án của bạn để khai thác tối đa tiềm năng của hệ thống và tối ưu hóa quá trình xử lý các tác vụ nặng.