PYTHON CONCURRENCY
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

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.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

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.

Cùng chuyên mục:

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn toàn diện về module datetime trong Python

Hướng dẫn toàn diện về module datetime trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Từ khóa yield trong Python

Từ khóa yield trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Định dạng chuỗi Strings trong Python

Định dạng chuỗi Strings trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Làm việc với các biến môi trường trong Python

Làm việc với các biến môi trường trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa iterator và iterable trong Python

Sự khác biệt giữa iterator và iterable trong Python

Cách làm việc với file tarball/tar trong Python

Cách làm việc với file tarball/tar trong Python

Chuyển đổi kiểu dữ liệu trong Python

Chuyển đổi kiểu dữ liệu trong Python

Sự khác biệt giữa toán tử == và is trong Python

Sự khác biệt giữa toán tử == và is trong Python

Làm việc với file ZIP trong Python

Làm việc với file ZIP trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Sự khác biệt giữa byte objects và string trong Python

Sự khác biệt giữa byte objects và string trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format  trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Top