콘텐츠로 바로 가기
STAGING SERVER
DEVELOPMENT SERVER

스레딩 및 동시성#

이 토픽에서는 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)
  • 생산자(Producer): 획득 스레드가 이미지를 캡처하여 큐에 푸시합니다.
  • 소비자(Consumer): 작업자 스레드가 독립적으로 이미지를 처리합니다.

사용자 지정 스레드를 사용한 구현 예시#

정보

InstantCamera에서 제공하는 grab loop 스레드를 사용할 수 있습니다(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()

큐 동작 및 배압(Backpressure)#

Queue full → producer blocks → acquisition slows down

전략:

  • 큐 크기를 늘립니다.
  • 프레임을 수동으로 드롭합니다.
  • 설정하려는 속성을 식별하려면 LatestImageOnly.

Grab Strategies와의 결합#

  • LatestImageOnly: 처리 적체를 줄입니다.
  • OneByOne: 완전성을 보장합니다.

권장 사례:

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

스레드 안전성 고려사항#

  • 락(Lock) 없이 변경 가능한(mutable) 데이터를 공유하지 마세요.
  • 예를 들어, 다음을 사용하여 이미지를 다른 스레드로 전달하기 전에 복사하십시오. 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

주요 핵심 사항#

  • 취득과 처리는 분리되어야 합니다.
  • 확장성을 위해 생산자-소비자 패턴을 사용하십시오.
  • 큐는 스레드 안전한 통신을 제공합니다.
  • 스레딩은 성능을 향상시키지만 복잡성을 증가시킵니다.