コンテンツにスキップ
ステージングサーバー
開発サーバー

スレッド処理と並行処理#

このトピックでは、pypylonアプリケーションにおけるスレッド処理と並行処理の使用方法、およびパフォーマンスと拡張性を考慮した画像取得・処理パイプラインの構築方法について説明します。

この視覚表現は、Pythonアプリケーションでの画像取得の仕組みを示しています。

Camera → Native Thread → Buffer Queue → Python Application
  • 画像取得は、pylon内のネイティブ(C++)スレッドで実行されます。
  • ユーザーのPythonコードは、バッファキューから画像を取得します。
  • この分離により、非同期取得が可能になります。

多くのアプリケーションでは、画像取得の速度が処理速度を上回ります:

Camera → 100 fps
Processing → 20 fps

並行処理を行わない場合:

  • バッファがFillでいっぱいになります。
  • フレームがドロップされます。
  • レイテンシが増加します。

基本的な実行モデル#

シングルスレッドアプローチは、画像取得パイプラインの最もシンプルな形式です。

Acquire → Process → Acquire → Process

例:

while camera.IsGrabbing():
    with camera.RetrieveResult(5000) as grab_result:
        if grab_result.GrabSucceeded():
            image = grab_result.Array
            process(image)

これには次のような欠点があります:

  • 処理が取得をブロックします。
  • CPU使用率が低い
  • スケーラビリティが限られている

これは、画像取得パイプラインに対するより洗練されたアプローチです。

Acquisition Thread → Queue → Worker Thread(s)
  • プロデューサー:取得スレッドが画像を取得し、キューにプッシュします。
  • Consumer: ワーカー スレッドが画像を独立して処理します。

カスタムスレッドを使用した実装例#

情報

InstantCameraが提供するグラブループスレッドを使用できます(grab_using_grab_loop_threadサンプルを参照してください)。これはデモンストレーション目的のみのカスタム実装です。

import threading
import queue
from pypylon import pylon

def process(image):
    print(image.shape)

image_queue = queue.Queue(maxsize=10)

# Producer thread
def grab_loop(camera):
    while camera.IsGrabbing():
        with camera.RetrieveResult(5000) as grab_result:
            if grab_result.GrabSucceeded():
                image = grab_result.Array
                image_queue.put(image)

# Consumer thread
def process_loop():
    while True:
        image = image_queue.get()
        process(image)
        image_queue.task_done()

with pylon.InstantCamera(pylon.FirstFound) as camera:
    camera.StartGrabbing()

    grab_thread = threading.Thread(target=grab_loop, args=(camera,))
    processing_thread = threading.Thread(target=process_loop)

    grab_thread.start()
    processing_thread.start()

    grab_thread.join()
    image_queue.join()

キューの動作とバックプレッシャー#

Queue full → producer blocks → acquisition slows down

ストラテジー:

  • キューサイズを増やす。
  • 手動でフレームをドロップする。
  • 使用 LatestImageOnly.

Grab Strategyとの組み合わせ#

  • LatestImageOnly:未処理の蓄積を軽減します。
  • OneByOne:完全性を確保します。

ベストプラクティス:

LatestImageOnly + queue → responsive systems
OneByOne + logging → analysis systems

スレッドセーフティに関する考慮事項#

  • ロックなしでミュータブルなデータを共有しないようにします。
  • 他のスレッドに画像を渡す前にコピーします。たとえば、 Array 関数と直接組み合わせて使用できます。
  • 使用 queue.Queue を使用して安全な通信を行います。

CPU使用率#

並列処理には以下の利点があります:

  • CPU使用率の向上
  • 関心の分離
  • スケーラブルなアーキテクチャ
Core 1 → Acquisition
Core 2 → Processing
Core 3 → AI

マルチスレッドを使用するタイミング#

次のような状況ではスレッドを使用します:

  • 処理速度が取り込み速度よりも遅い。
  • 複数の処理ステージが存在する。
  • リアルタイムの応答性が求められる。

次のような状況ではスレッドを使用しないようにします:

  • 処理負荷がごくわずかである。
  • システム記述は最小限に抑える必要があります。

高度なパターン(概要)#

マルチステージパイプライン#

多段階のパイプラインにより、画像処理が並行して実行されキューを介してデータを交換する独立したステップに分割されます。

Grab → Preprocess → Analyze → Display

マルチコンシューマー構成#

Producer → Queue → Multiple processing threads

概念的なパイプライン#

Camera → Queue → Processing → Results

主なポイント#

  • 取り込みと処理は分離する必要があります。
  • 拡張性のためにプロデューサー・コンシューマー・パターンを使用します。
  • キューにより、スレッドセーフな通信が提供されます。
  • スレッド化によりパフォーマンスは向上しますが、複雑さが増します。