コンテンツにスキップ

YOLOモデルを使用したスレッドセーフな推論

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



見る: pythonでUltralytics YOLOモデルを使用したスレッドセーフな推論を実行する方法 | マルチスレッディング 🚀

pythonスレッドの理解

Python のスレッドは、プログラムが複数の操作を同時に実行できる並列処理の一形態です。ただし、Python の Global Interpreter Lock (GIL) により、一度に 1 つのスレッドしか Python バイトコードを実行できません。

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

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

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

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

非スレッドセーフの例:単一のモデルインスタンス

pythonでスレッドを使用する場合、並行性の問題につながる可能性のあるパターンを認識することが重要です。複数のスレッド間で単一のYOLOモデルインスタンスを共有することは避けてください。

# 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("yolo11n.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 threading import Thread

from ultralytics import YOLO

# Instantiate multiple models outside the thread
shared_model_1 = YOLO("yolo11n_1.pt")
shared_model_2 = YOLO("yolo11n_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 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("yolo11n.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 インスタンスを使用します。これにより、あるスレッドが別のスレッドのモデル状態を妨害することを防ぎ、各スレッドが安全に、かつ他のスレッドとの予期しない相互作用なしに推論を実行できるようにします。

ThreadingLockedデコレーターの使用

Ultralyticsは、 ThreadingLocked 関数をスレッドセーフに実行できるようにするためのデコレータ。このデコレータは、ロックを使用して、一度に1つのスレッドだけがデコレートされた関数を実行できるようにします。

from ultralytics import YOLO
from ultralytics.utils import ThreadingLocked

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


# Decorate the predict method 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

The ThreadingLocked デコレータは、スレッド間でモデルインスタンスを共有する必要があるものの、一度に1つのスレッドだけがアクセスできるようにする必要がある場合に特に役立ちます。このアプローチは、スレッドごとに新しいモデルインスタンスを作成するよりもメモリを節約できますが、スレッドがロックの解除を待つ必要があるため、並行性が低下する可能性があります。

結論

pythonのYOLOモデルを使用する場合 threading)は、スレッドセーフを確保するために、モデルを使用するスレッド内で常にインスタンス化してください。この方法により、競合状態が回避され、推論タスクが確実に実行されるようになります。

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

よくある質問

マルチスレッドのpython環境でYOLOモデルを使用する際に、競合状態を回避するにはどうすればよいですか?

マルチスレッドpython環境でUltralytics YOLOモデルを使用する場合の競合状態を防ぐには、各スレッド内に個別のYOLOモデルをインスタンス化します。これにより、各スレッドが独自の分離されたモデルインスタンスを持つことが保証され、モデル状態の同時変更が回避されます。

例:

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

スレッドセーフを確保するための詳細については、YOLOモデルによるスレッドセーフな推論をご覧ください。

PythonでマルチスレッドYOLOモデル推論を実行するためのベストプラクティスは何ですか?

pythonでマルチスレッドYOLOモデル推論を安全に実行するには、以下のベストプラクティスに従ってください。

  1. スレッド間で単一のモデルインスタンスを共有するのではなく、各スレッド内で YOLO モデルをインスタンス化します。
  2. pythonの以下を使用します: multiprocessing モジュールを使用して並列処理を行い、Global Interpreter Lock(GIL)に関連する問題を回避します。
  3. YOLOの基盤となるCライブラリによって実行される操作を使用して、GILを解放します。
  4. 以下をご検討ください。 ThreadingLocked メモリが懸念される場合の共有モデルインスタンス用のデコレータ。

スレッドセーフなモデルインスタンス化の例:

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."""
    model = YOLO("yolo11n.pt")
    results = 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()

追加のコンテキストについては、スレッドセーフな推論に関するセクションを参照してください。

各スレッドが独自のYOLOモデルインスタンスを持つべきなのはなぜですか?

各スレッドは、競合状態を防ぐために、それぞれ独自のYOLOモデルインスタンスを持つ必要があります。単一のモデルインスタンスを複数のスレッドで共有すると、同時アクセスによって予測不能な動作やモデル内部状態の変更が発生する可能性があります。個別のインスタンスを使用することで、スレッドの分離が保証され、マルチスレッドタスクの信頼性と安全性が向上します。

詳細なガイダンスについては、非スレッドセーフの例:単一モデルインスタンスおよびスレッドセーフの例セクションを確認してください。

pythonのGlobal Interpreter Lock(GIL)は、YOLOモデルの推論にどのように影響しますか?

Python の Global Interpreter Lock (GIL) は、一度に 1 つのスレッドしか Python バイトコードを実行できないため、CPU バウンドのマルチスレッドタスクのパフォーマンスが制限される可能性があります。ただし、I/O バウンドの操作や、YOLO の基盤となる C ライブラリのように GIL を解放するライブラリを使用するプロセスの場合、並行性を実現できます。パフォーマンスを向上させるには、Python の multiprocessing モジュールを使用したプロセスベースの multiprocessing モジュール。

pythonにおけるスレッディングの詳細については、pythonスレッディングの理解のセクションを参照してください。

YOLOモデルの推論にスレッド処理の代わりにプロセスベースの並列処理を使用する方が安全ですか?

はい、pythonの multiprocessing モジュールを使用する方が安全であり、多くの場合、YOLOモデルの推論を並行して実行する方が効率的です。プロセスベースの並列処理では、個別のメモリー空間が作成され、Global Interpreter Lock(GIL)が回避され、並行処理の問題のリスクが軽減されます。各プロセスは、独自のYOLOモデルインスタンスを使用して独立して動作します。

YOLOモデルを使用したプロセスベースの並列処理の詳細については、Thread-Safe Inferenceのページを参照してください。



📅 1年前に作成 ✏️ 3ヶ月前に更新

コメント