Link to this sectionYOLO モデルによるスレッドセーフな推論#
Pythonの各スレッドで安全に Ultralytics YOLO 推論を実行するには、1つのインスタンスを共有するのではなく、スレッドごとに個別の YOLO モデルをインスタンス化してください。単一のモデルを共有すると、Pythonの threading モジュールが同じオブジェクトに対してスレッドを並行実行する際に競合状態(レースコンディション)が発生し、内部状態が壊れて予測不可能な結果が生じる可能性があります。本ガイドでは、なぜ共有が失敗するのか、スレッドごとの安全なパターン、およびインスタンスを共有しなければならない場合の ThreadingLocked デコレータについて解説します。
モデル共有が失敗する理由、スレッドセーフなパターン、または ThreadingLocked デコレータへジャンプします。
Watch: How to Perform Thread Safe Inference with Ultralytics YOLO Models in Python | Multi-Threading 🚀
Link to this sectionPython スレッドの理解#
Python スレッドは、プログラムが複数の操作を同時に実行できるようにする並列処理の一形態です。しかし、Python のグローバルインタプリタロック(GIL)により、一度に実行できる Python バイトコードは 1 つのスレッドのみです。
これは制限のように聞こえますが、スレッドは依然として並行性を提供します。特に I/O バウンドな操作や、YOLO の基盤となる C ライブラリによって実行される操作のように、GIL を解放する操作を使用する場合に有効です。
Link to this section共有モデルインスタンスの危険性#
YOLO モデルをスレッドの外でインスタンス化し、そのインスタンスを複数のスレッド間で共有すると、レースコンディションが発生する可能性があります。これは、同時アクセスによってモデルの内部状態が矛盾した形で変更されるためです。モデルやそのコンポーネントがスレッドセーフではない状態を保持している場合、特に問題となります。
Link to this sectionスレッドセーフではない例:単一モデルインスタンス#
Pythonでスレッドを使用する際は、同時実行性の問題につながるパターンを認識しておくことが重要です。避けるべきパターンとして、単一の YOLO26 モデルインスタンスを複数のスレッド間で共有することが挙げられます。
# 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()上記の例では、shared_model が複数のスレッドによって使用されています。predict が複数のスレッドによって同時に実行される可能性があるため、予測不能な結果を招く恐れがあります。
Link to this section安全な例:スレッドごとの専用インスタンス#
複数の個別のモデルインスタンスは、各スレッドが自身のインスタンスを所有し、他のスレッドと共有しない限り問題ありません。以下のインスタンスがスレッド開始前に作成されているかどうかは重要ではなく、唯一の安全でないパターンは1つのインスタンスをスレッド間で共有することです。
# 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()各スレッドは独自の専用インスタンスで動作するため、スレッドが壊すような共有モデル状態は存在しません。次に示すように、モデルを各スレッド内でインスタンス化することが、インスタンスが誤って共有されることを防ぐ最も簡単な方法です。
Link to this sectionスレッドセーフな推論#
スレッドセーフな推論を行うには、各スレッド内で個別の YOLO モデルをインスタンス化する必要があります。これにより、各スレッドが独自の独立したモデルインスタンスを持つようになり、レースコンディションのリスクが排除されます。
Link to this sectionスレッドセーフな例#
安全な並列推論のために、各スレッド内で 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("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()この例では、各スレッドが独自の YOLO インスタンスを作成します。これにより、あるスレッドが他のスレッドのモデル状態に干渉することを防ぎ、各スレッドが他のスレッドとの予期せぬ相互作用なしに安全に推論を実行できるようになります。
Link to this sectionThreadingLocked デコレータの使用#
Ultralytics は、関数のスレッドセーフな実行を保証するために使用できる ThreadingLocked デコレータを提供しています。このデコレータはロックを使用して、一度に1つのスレッドのみがデコレータ付き関数を実行できるようにします。
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 threadsThreadingLocked デコレータは、モデルインスタンスをスレッド間で共有する必要があるものの、一度に1つのスレッドしかアクセスできないようにしたい場合に特に役立ちます。
ロックされたモデルインスタンスを共有することは、すべてのスレッドでモデルを読み込む場合に比べて メモリを節約 できますが、スレッドがロックを待機して直列化されるため 同時実行性が低下 します。メモリに余裕があり、最大限の並列処理を行いたい場合はスレッドごとのパターンを優先し、モデルのメモリがボトルネックとなる場合に ThreadingLocked を検討してください。
Link to this section結論#
Pythonの threading でYOLOモデルを使用する場合は、各スレッドに専用のモデルインスタンスを与え、1つのインスタンスをスレッド間で共有しないでください。それを使用するスレッド内でモデルをインスタンス化することが、これを保証し、競合状態を回避して推論タスクを確実に維持する最もシンプルな方法です。
より高度なシナリオやマルチスレッド推論パフォーマンスのさらなる最適化については、multiprocessing を使用したプロセスベースの並列処理、または専用のワーカープロセスを持つタスクキューの活用を検討してください。
Link to this sectionよくある質問 (FAQ)#
Link to this sectionマルチスレッド 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("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()スレッドセーフの確保に関する詳細については、YOLO モデルによるスレッドセーフな推論 を参照してください。
Link to this sectionPython でマルチスレッド YOLO モデル推論を実行するためのベストプラクティスは何ですか?#
Python でマルチスレッド YOLO モデル推論を安全に実行するには、以下のベストプラクティスに従ってください。
- 単一のモデルインスタンスをスレッド間で共有するのではなく、各スレッド内で YOLO モデルをインスタンス化してください。
- グローバルインタプリタロック(GIL)に関連する問題を回避するには、並列処理のためにPythonの
multiprocessingモジュールを使用してください。 - YOLOの基盤となるCライブラリ(PyTorch、OpenCV)は、負荷の高い計算中に自動的にGILを解放するため、スレッドは依然として並行して推論を実行できることに注意してください。
- メモリが懸念される場合は、共有モデルインスタンスに対して
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."""
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()詳細な背景については、スレッドセーフな推論 のセクションを参照してください。
Link to this sectionなぜ各スレッドが独自の YOLO モデルインスタンスを持つべきなのですか?#
各スレッドが独自の YOLO モデルインスタンスを持つべきなのは、レースコンディションを防ぐためです。単一のモデルインスタンスが複数のスレッド間で共有されると、同時アクセスによって予測不能な動作やモデルの内部状態の変更が発生する可能性があります。別々のインスタンスを使用することでスレッドの分離が確保され、マルチスレッドタスクが信頼性の高い安全なものになります。
詳細なガイダンスについては、スレッドセーフではない例:単一モデルインスタンス および スレッドセーフな例 セクションを確認してください。
Link to this sectionPython のグローバルインタプリタロック(GIL)は YOLO モデルの推論にどのような影響を与えますか?#
Python のグローバルインタプリタロック(GIL)は、一度に 1 つのスレッドのみが Python バイトコードを実行できるようにするため、CPU バウンドなマルチスレッドタスクのパフォーマンスを制限する可能性があります。しかし、I/O バウンドな操作や、YOLO の基盤となる C ライブラリのように GIL を解放するライブラリを使用するプロセスでは、依然として並行性を達成可能です。パフォーマンスを向上させるには、Python の multiprocessing モジュールを使用したプロセスベースの並列処理を検討してください。
Python におけるスレッドの詳細については、Python スレッドの理解 セクションを参照してください。
Link to this sectionYOLO モデルの推論において、スレッド処理の代わりにプロセスベースの並列処理を使用する方が安全ですか?#
はい、Python の multiprocessing モジュールを使用する方が安全であり、多くの場合、YOLO モデルの推論を並列実行するのに効率的です。プロセスベースの並列処理は個別のメモリ領域を作成するため、グローバルインタプリタロック(GIL)を回避し、同時実行性の問題のリスクを軽減します。各プロセスは独自の YOLO モデルインスタンスを持ち、独立して動作します。
YOLO モデルによるプロセスベースの並列処理の詳細については、スレッドセーフな推論 のページを参照してください。