Ultralytics YOLO27:

Suy luận an toàn luồng với các model YOLO#

Để chạy suy luận Ultralytics YOLO an toàn trên các luồng Python, hãy khởi tạo một model YOLO riêng bên trong mỗi luồng thay vì chia sẻ một instance giữa các luồng. Việc chia sẻ một model duy nhất gây ra các điều kiện tranh chấp làm hỏng trạng thái nội bộ của model và tạo ra kết quả không thể dự đoán, vì module threading của Python chạy đồng thời các luồng trên cùng một object. Hướng dẫn này giải thích lý do việc chia sẻ không hoạt động, trình bày mẫu an toàn theo từng luồng và đề cập đến decorator ThreadingLocked trong các trường hợp bạn bắt buộc phải chia sẻ một instance.

Chuyển đến phần tại sao việc chia sẻ model không hoạt động, mẫu an toàn cho luồng hoặc decorator ThreadingLocked.



Watch: How to Perform Thread Safe Inference with Ultralytics YOLO Models in Python | Multi-Threading 🚀

Tìm hiểu về Threading trong Python#

Các luồng Python là một dạng xử lý song song cho phép chương trình chạy nhiều thao tác cùng lúc. Tuy nhiên, Global Interpreter Lock (GIL) của Python có nghĩa là mỗi lần chỉ một luồng có thể thực thi bytecode Python.

Single-thread vs multi-thread inference

Mặc dù nghe có vẻ là một hạn chế, các luồng vẫn có thể cung cấp khả năng đồng thời, đặc biệt đối với các thao tác bị giới hạn bởi I/O hoặc khi sử dụng những thao tác giải phóng GIL, chẳng hạn các thao tác do các thư viện C nền tảng của YOLO thực hiện.

Rủi ro khi chia sẻ các instance model#

Việc khởi tạo một model YOLO bên ngoài các luồng rồi chia sẻ instance này cho nhiều luồng có thể dẫn đến các điều kiện tranh chấp, trong đó trạng thái nội bộ của model bị sửa đổi không nhất quán do các lượt truy cập đồng thời. Điều này đặc biệt đáng lo ngại khi model hoặc các thành phần của nó lưu giữ trạng thái không được thiết kế để an toàn luồng.

Ví dụ không an toàn luồng: Một instance model duy nhất#

Khi sử dụng các luồng trong Python, điều quan trọng là phải nhận diện những mẫu có thể dẫn đến sự cố đồng thời. Sau đây là điều bạn nên tránh: chia sẻ một instance model YOLO26 duy nhất cho nhiều luồng.

# Unsafe: Sharing a single model instance across threads
from threading import Thread

from ultralytics import YOLO

# Instantiate the model outside the thread
shared_model = YOLO("yolo26n.pt")

def predict(image_path):
    """Predicts objects in an image using a preloaded YOLO model, take path string to image as argument."""
    results = shared_model.predict(image_path)
    # Process results

# Starting threads that share the same model instance
Thread(target=predict, args=("image1.jpg",)).start()
Thread(target=predict, args=("image2.jpg",)).start()

Trong ví dụ trên, shared_model được nhiều luồng sử dụng, điều này có thể dẫn đến kết quả không thể dự đoán vì predict có thể được nhiều luồng thực thi đồng thời.

Ví dụ an toàn: Một instance dành riêng cho mỗi luồng#

Có thể sử dụng nhiều instance model riêng biệt, miễn là mỗi luồng sở hữu instance của mình và không bao giờ chia sẻ instance đó với luồng khác. Việc các instance bên dưới được tạo trước khi các luồng bắt đầu không quan trọng — mẫu duy nhất không an toàn là chia sẻ một instance giữa các luồng:

# Safe: each thread uses its own dedicated model instance
from threading import Thread

from ultralytics import YOLO

# Instantiate one model per thread
model_1 = YOLO("yolo26n.pt")
model_2 = YOLO("yolo26n.pt")

def predict(model, image_path):
    """Runs prediction on an image using a specified YOLO model, returning the results."""
    results = model.predict(image_path)
    # Process results

# Each thread uses a separate, dedicated model instance
Thread(target=predict, args=(model_1, "image1.jpg")).start()
Thread(target=predict, args=(model_2, "image2.jpg")).start()

Vì mỗi luồng làm việc với instance dành riêng của mình nên không có trạng thái model dùng chung để các luồng làm hỏng. Việc khởi tạo model bên trong mỗi luồng, như minh họa tiếp theo, đơn giản là cách dễ nhất để đảm bảo một instance không bao giờ vô tình bị chia sẻ.

Suy luận an toàn luồng#

Để thực hiện suy luận an toàn luồng, bạn nên khởi tạo một model YOLO riêng bên trong mỗi luồng. Điều này đảm bảo mỗi luồng có một instance model biệt lập, loại bỏ nguy cơ xảy ra các điều kiện tranh chấp.

Ví dụ an toàn luồng#

Sau đây là cách khởi tạo một model YOLO bên trong mỗi luồng để thực hiện suy luận song song an toàn:

# Safe: Instantiating a single model inside each thread
from threading import Thread

from ultralytics import YOLO

def thread_safe_predict(image_path):
    """Predict on an image using a new YOLO model instance in a thread-safe manner; takes image path as input."""
    local_model = YOLO("yolo26n.pt")
    results = local_model.predict(image_path)
    # Process results

# Starting threads that each have their own model instance
Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

Trong ví dụ này, mỗi luồng tạo instance YOLO riêng. Điều này ngăn mọi luồng can thiệp vào trạng thái model của luồng khác, từ đó đảm bảo mỗi luồng thực hiện suy luận an toàn và không xảy ra tương tác ngoài dự kiến với các luồng khác.

Sử dụng decorator ThreadingLocked#

Ultralytics cung cấp decorator ThreadingLocked, có thể được sử dụng để đảm bảo các hàm thực thi an toàn luồng. Decorator này sử dụng một lock để đảm bảo mỗi lần chỉ một luồng có thể thực thi hàm được trang trí.

from ultralytics import YOLO
from ultralytics.utils import ThreadingLocked

# Create a model instance
model = YOLO("yolo26n.pt")

# Decorate the prediction function to make it thread-safe
@ThreadingLocked()
def thread_safe_predict(image_path):
    """Thread-safe prediction using a shared model instance."""
    results = model.predict(image_path)
    return results

# Now you can safely call this function from multiple threads

Decorator ThreadingLocked đặc biệt hữu ích khi bạn cần chia sẻ một instance model giữa các luồng nhưng muốn đảm bảo mỗi lần chỉ một luồng có thể truy cập instance đó.

Đánh đổi giữa bộ nhớ và tính đồng thời

Chia sẻ một instance model có lock tiết kiệm bộ nhớ so với việc tải một model trong mỗi luồng, nhưng làm giảm tính đồng thời vì các luồng phải tuần tự hóa khi chờ lock và lần lượt thực thi. Hãy ưu tiên mẫu theo từng luồng khi bạn còn đủ bộ nhớ và muốn đạt mức song song tối đa, đồng thời sử dụng ThreadingLocked khi bộ nhớ dành cho model là nút thắt.

Kết luận#

Khi sử dụng các model YOLO với threading của Python, hãy cấp cho mỗi luồng một instance model dành riêng và không bao giờ chia sẻ một instance giữa các luồng. Việc khởi tạo model bên trong luồng sử dụng nó là cách đơn giản nhất để đảm bảo điều này, tránh các điều kiện tranh chấp và duy trì độ tin cậy cho các tác vụ suy luận.

Đối với các kịch bản nâng cao hơn và để tiếp tục tối ưu hiệu năng suy luận đa luồng, hãy cân nhắc sử dụng xử lý song song dựa trên process với multiprocessing hoặc tận dụng hàng đợi tác vụ cùng các process worker chuyên dụng.

FAQ#

  • Để ngăn các điều kiện tranh chấp khi sử dụng các model Ultralytics YOLO trong môi trường Python đa luồng, hãy khởi tạo một model YOLO riêng bên trong mỗi luồng. Điều này đảm bảo mỗi luồng có một instance model biệt lập, tránh việc trạng thái model bị sửa đổi đồng thời.

    Ví dụ:

    from threading import Thread
    
    from ultralytics import YOLO
    
    def thread_safe_predict(image_path):
        """Predict on an image in a thread-safe manner."""
        local_model = YOLO("yolo26n.pt")
        results = local_model.predict(image_path)
        # Process results
    
    Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
    Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

    Để biết thêm thông tin về việc đảm bảo an toàn luồng, hãy truy cập Suy luận an toàn luồng với các model YOLO.

  • Để chạy suy luận model YOLO đa luồng an toàn trong Python, hãy tuân theo các phương pháp tốt nhất sau:

    1. Khởi tạo các model YOLO trong từng luồng thay vì chia sẻ một instance model duy nhất giữa các luồng.
    2. Sử dụng module multiprocessing của Python để xử lý song song nhằm tránh các vấn đề liên quan đến Global Interpreter Lock (GIL).
    3. Hãy nhớ rằng các thư viện C nền tảng của YOLO (PyTorch, OpenCV) tự động giải phóng GIL trong quá trình tính toán nặng, vì vậy các luồng vẫn có thể chạy suy luận đồng thời.
    4. Hãy cân nhắc sử dụng decorator ThreadingLocked cho các instance model dùng chung khi bộ nhớ là mối quan tâm.

    Ví dụ về khởi tạo model an toàn luồng:

    from threading import Thread
    
    from ultralytics import YOLO
    
    def thread_safe_predict(image_path):
        """Runs inference in a thread-safe manner with a new YOLO model instance."""
        local_model = YOLO("yolo26n.pt")
        results = local_model.predict(image_path)
        # Process results
    
    # Initiate multiple threads
    Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
    Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

    Để biết thêm bối cảnh, hãy tham khảo phần Suy luận an toàn luồng.

  • Mỗi luồng nên có instance model YOLO riêng để ngăn các điều kiện tranh chấp. Khi một instance model duy nhất được chia sẻ giữa nhiều luồng, các lượt truy cập đồng thời có thể dẫn đến hành vi không thể dự đoán và việc sửa đổi trạng thái nội bộ của model. Bằng cách sử dụng các instance riêng biệt, bạn đảm bảo sự cô lập giữa các luồng, giúp các tác vụ đa luồng đáng tin cậy và an toàn.

    Để xem hướng dẫn chi tiết, hãy tham khảo các phần Ví dụ không an toàn luồng: Một instance model duy nhấtVí dụ an toàn luồng.

  • Global Interpreter Lock (GIL) của Python chỉ cho phép một luồng thực thi bytecode Python tại một thời điểm, điều này có thể hạn chế hiệu năng của các tác vụ đa luồng bị giới hạn bởi CPU. Tuy nhiên, đối với các thao tác bị giới hạn bởi I/O hoặc những process sử dụng các thư viện giải phóng GIL, chẳng hạn các thư viện C nền tảng của YOLO, bạn vẫn có thể đạt được tính đồng thời. Để cải thiện hiệu năng, hãy cân nhắc sử dụng xử lý song song dựa trên process với module multiprocessing của Python.

    Để tìm hiểu thêm về threading trong Python, hãy xem phần Tìm hiểu về Threading trong Python.

  • Có, sử dụng module multiprocessing của Python an toàn hơn và thường hiệu quả hơn khi chạy suy luận model YOLO song song. Xử lý song song dựa trên process tạo ra các không gian bộ nhớ riêng biệt, tránh Global Interpreter Lock (GIL) và giảm nguy cơ xảy ra các vấn đề về tính đồng thời. Mỗi process sẽ hoạt động độc lập với instance model YOLO riêng.

    Để biết thêm chi tiết về xử lý song song dựa trên process với các model YOLO, hãy tham khảo trang Suy luận an toàn luồng.

Bình luận