コンテンツへスキップ

YOLO モデルによるスレッドセーフ推論

マルチスレッド環境でYOLO モデルを実行するには、スレッドセーフを確保するための慎重な配慮が必要です。Python's threading モジュールでは複数のスレッドを同時に実行することができますが、これらのスレッドにまたがってYOLO モデルを使用する場合、注意すべき重要な安全上の問題があります。このページでは、スレッドセーフなYOLO モデル推論を作成する方法を説明します。

Python スレッドを理解する

Python スレッドは並列処理の一形態で、プログラムが一度に複数の処理を実行できるようにする。しかし、Python'のグローバル・インタープリタ・ロック(GIL)は、Python バイトコードを一度に実行できるスレッドが1つだけであることを意味する。

シングルスレッドとマルチスレッドの例

これは制限のように聞こえるが、スレッドは、特にI/Oバウンド操作や、YOLO'の基礎となるCライブラリによって実行されるようなGILを解放する操作を使用する場合に、依然として並行性を提供することができる。

共有モデル・インスタンスの危険性

スレッド外でYOLO モデルをインスタンス化し、このインスタンスを複数のスレッドで共有すると、同時アクセスによってモデルの内部状態が矛盾して変更される競合状態が発生する可能性があります。これは、モデルやそのコンポーネントがスレッドセーフに設計されていない状態を保持している場合に特に問題となります。

スレッドセーフでない例:単一モデルインスタンス

Python でスレッドを使用する場合、同時実行の問題につながるパターンを認識することが重要です。ここで避けるべきことは、1つのYOLO モデルのインスタンスを複数のスレッドで共有することです。

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

# Instantiate the model outside the thread
shared_model = YOLO("yolov8n.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()

上記の例では shared_model は複数のスレッドで使用されるため、予測不可能な結果につながる可能性があります。 predict は複数のスレッドによって同時に実行される可能性がある。

スレッドセーフでない例:複数のモデルインスタンス

同様に、YOLO モデルインスタンスを複数持つ安全でないパターンを紹介する:

# Unsafe: Sharing multiple model instances across threads can still lead to issues
from ultralytics import YOLO
from threading import Thread

# Instantiate multiple models outside the thread
shared_model_1 = YOLO("yolov8n_1.pt")
shared_model_2 = YOLO("yolov8n_2.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


# Starting threads with individual model instances
Thread(target=predict, args=(shared_model_1, "image1.jpg")).start()
Thread(target=predict, args=(shared_model_2, "image2.jpg")).start()

2つの別々のモデル・インスタンスがあっても、並行性の問題のリスクはまだ存在する。もし YOLO がスレッドセーフでない場合、特にこれらのインスタンスがスレッドローカルでない基礎的なリソースやステートを共有している場合、別々のインスタンスを使用しても競合状態を防げない可能性がある。

スレッドセーフ推論

スレッドセーフな推論を行うためには、各スレッド内で別々のYOLO ・モデルをインスタンス化する必要がある。こうすることで、各スレッドがそれぞれ独立したモデル・インスタンスを持つようになり、競合状態が発生するリスクがなくなります。

スレッドセーフの例

ここでは、安全な並列推論を行うために、各スレッド内でYOLO モデルをインスタンス化する方法を説明する:

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


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("yolov8n.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()

この例では、各スレッドが YOLO インスタンスを作成する。これにより、どのスレッドも他のスレッドのモデル状態に干渉することがなくなり、各スレッドが他のスレッドと予期せぬ相互作用をすることなく、安全に推論を実行できるようになる。

結論

Python のYOLO モデルを使用する場合。 threadingスレッドセーフを保証するために、常にモデルを使用するスレッド内でインスタンス化する。こうすることで、競合状態を回避し、推論タスクを確実に実行することができます。

より高度なシナリオや、マルチスレッド推論のパフォーマンスをさらに最適化するには、次のようなプロセスベースの並列処理を使用することを検討します。 multiprocessing あるいは、専用のワーカープロセスでタスクキューを活用する。



作成日:2023-11-12 更新日:2024-05-03
作成者:glenn-jocher(2)

コメント