YOLO 모델의 스레드 안전 추론#
Python 스레드 전반에서 Ultralytics YOLO 추론을 안전하게 실행하려면, 하나의 인스턴스를 여러 스레드에서 공유하는 대신 각 스레드 안에 별도의 YOLO 모델을 생성하세요. 단일 모델을 공유하면 경쟁 조건이 발생하여 내부 상태가 손상되고 예측할 수 없는 결과가 나올 수 있습니다. 이는 Python의 threading 모듈이 동일한 객체를 대상으로 여러 스레드를 동시에 실행하기 때문입니다. 이 가이드에서는 공유 방식이 실패하는 이유를 설명하고, 스레드별로 안전하게 모델을 사용하는 패턴과 인스턴스를 공유해야 할 때 사용할 수 있는 ThreadingLocked 데코레이터를 소개합니다.
모델 공유가 실패하는 이유, 스레드 안전 패턴 또는 ThreadingLocked 데코레이터로 이동하세요.
시청: Python에서 Ultralytics YOLO 모델로 스레드 안전 추론을 수행하는 방법 | 멀티스레딩 🚀
Python 스레딩 이해하기#
Python 스레드는 프로그램에서 여러 작업을 동시에 실행할 수 있게 해주는 병렬 처리 방식입니다. 하지만 Python의 전역 인터프리터 잠금(GIL)으로 인해 한 번에 하나의 스레드만 Python 바이트코드를 실행할 수 있습니다.
이는 제한 사항처럼 보일 수 있지만, 스레드는 여전히 동시성을 제공할 수 있습니다. 특히 I/O 바운드 작업이나 YOLO의 기반 C 라이브러리에서 수행되는 것처럼 GIL을 해제하는 연산을 사용할 때 효과적입니다.
모델 인스턴스 공유의 위험성#
스레드 외부에서 YOLO 모델을 생성한 다음 여러 스레드에서 해당 인스턴스를 공유하면, 동시 접근으로 인해 모델의 내부 상태가 일관성 없이 수정되는 경쟁 조건이 발생할 수 있습니다. 모델 또는 구성 요소가 스레드 안전성을 고려해 설계되지 않은 상태를 보유할 경우 특히 문제가 됩니다.
스레드 안전하지 않은 예: 단일 모델 인스턴스#
Python에서 스레드를 사용할 때는 동시성 문제를 일으킬 수 있는 패턴을 파악하는 것이 중요합니다. 다음은 피해야 할 패턴입니다. 하나의 YOLO26 모델 인스턴스를 여러 스레드에서 공유하는 것입니다.
# 안전하지 않음: 단일 모델 인스턴스를 여러 스레드에서 공유
from threading import Thread
from ultralytics import YOLO
# 스레드 외부에서 모델 생성
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)
# 결과를 처리합니다
# 동일한 모델 인스턴스를 공유하는 스레드 시작
Thread(target=predict, args=("image1.jpg",)).start()
Thread(target=predict, args=("image2.jpg",)).start()위 예제에서는 여러 스레드가 shared_model을 사용하므로 예측할 수 없는 결과가 발생할 수 있습니다. predict이 여러 스레드에서 동시에 실행될 수 있기 때문입니다.
안전한 예: 스레드마다 전용 인스턴스 사용#
각 스레드가 자체 인스턴스를 소유하고 다른 스레드와 공유하지 않는다면, 별도의 모델 인스턴스를 여러 개 사용해도 괜찮습니다. 아래 인스턴스가 스레드 시작 전에 생성되더라도 문제되지 않습니다. 안전하지 않은 패턴은 단일 인스턴스를 여러 스레드에서 공유하는 경우뿐입니다.
# 안전함: 각 스레드가 자체 전용 모델 인스턴스를 사용
from threading import Thread
from ultralytics import YOLO
# 스레드마다 모델 하나 생성
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)
# 결과를 처리합니다
# 각 스레드가 별도의 전용 모델 인스턴스를 사용
Thread(target=predict, args=(model_1, "image1.jpg")).start()
Thread(target=predict, args=(model_2, "image2.jpg")).start()각 스레드가 자체 전용 인스턴스를 사용하므로 스레드가 손상시킬 공유 모델 상태가 없습니다. 다음 예제처럼 각 스레드 안에서 모델을 생성하는 방식은 인스턴스가 실수로 공유되지 않도록 보장하는 가장 쉬운 방법입니다.
스레드 안전 추론#
스레드 안전 추론을 수행하려면 각 스레드 안에 별도의 YOLO 모델을 생성해야 합니다. 이렇게 하면 각 스레드에 격리된 모델 인스턴스가 할당되어 경쟁 조건의 위험을 제거할 수 있습니다.
스레드 안전 예제#
안전한 병렬 추론을 위해 각 스레드 안에 YOLO 모델을 생성하는 방법은 다음과 같습니다.
# 안전함: 각 스레드 안에 단일 모델 인스턴스 생성
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)
# 결과를 처리합니다
# 각 스레드가 자체 모델 인스턴스를 갖도록 스레드를 시작합니다
Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
Thread(target=thread_safe_predict, args=("image2.jpg",)).start()이 예제에서는 각 스레드가 자체 YOLO 인스턴스를 생성합니다. 이렇게 하면 스레드 간에 다른 스레드의 모델 상태를 간섭할 수 없으므로 각 스레드가 다른 스레드와 예기치 않게 상호 작용하지 않고 안전하게 추론을 수행합니다.
ThreadingLocked 데코레이터 사용#
Ultralytics는 함수의 스레드 안전 실행을 보장하는 데 사용할 수 있는 ThreadingLocked 데코레이터를 제공합니다. 이 데코레이터는 잠금을 사용하여 한 번에 하나의 스레드만 데코레이터가 적용된 함수를 실행하도록 합니다.
from ultralytics import YOLO
from ultralytics.utils import ThreadingLocked
# 모델 인스턴스 생성
model = YOLO("yolo26n.pt")
# 예측 함수에 데코레이터를 적용하여 스레드 안전성 확보
@ThreadingLocked()
def thread_safe_predict(image_path):
"""Thread-safe prediction using a shared model instance."""
results = model.predict(image_path)
return results
# 이제 여러 스레드에서 이 함수를 안전하게 호출할 수 있습니다.ThreadingLocked 데코레이터는 여러 스레드에서 모델 인스턴스를 공유해야 하지만 한 번에 하나의 스레드만 해당 인스턴스에 접근하도록 해야 할 때 특히 유용합니다.
잠금이 적용된 모델 인스턴스 하나를 공유하면 모든 스레드에서 모델을 로드하는 것보다 메모리를 절약할 수 있지만, 스레드가 잠금에 따라 차례로 실행되고 대기하므로 동시성이 낮아집니다. 메모리에 여유가 있고 병렬성을 극대화하려면 스레드별 패턴을 사용하고, 모델 메모리가 병목인 경우에는 ThreadingLocked을 사용하세요.
결론#
YOLO 모델을 Python의 threading과 함께 사용할 때는 각 스레드에 자체 전용 모델 인스턴스를 할당하고, 하나의 인스턴스를 여러 스레드에서 공유하지 마세요. 모델을 사용하는 스레드 안에서 모델을 생성하는 것이 이를 보장하는 가장 간단한 방법이며, 경쟁 조건을 방지하고 추론 작업의 안정성을 유지할 수 있습니다.
더 고급 시나리오에서 멀티스레드 추론 성능을 추가로 최적화하려면 multiprocessing을 사용한 프로세스 기반 병렬 처리나 전용 워커 프로세스를 사용하는 작업 큐를 고려해 보세요.
자주 묻는 질문#
멀티스레드 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) # 결과를 처리합니다 Thread(target=thread_safe_predict, args=("image1.jpg",)).start() Thread(target=thread_safe_predict, args=("image2.jpg",)).start()스레드 안전성을 보장하는 방법에 대한 자세한 내용은 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) # 결과를 처리합니다 # 여러 스레드 시작 Thread(target=thread_safe_predict, args=("image1.jpg",)).start() Thread(target=thread_safe_predict, args=("image2.jpg",)).start()추가 설명은 스레드 안전 추론 섹션을 참조하세요.
경쟁 조건을 방지하려면 각 스레드가 자체 YOLO 모델 인스턴스를 가져야 합니다. 단일 모델 인스턴스를 여러 스레드에서 공유하면 동시 접근으로 예측할 수 없는 동작이 발생하고 모델의 내부 상태가 수정될 수 있습니다. 별도의 인스턴스를 사용하면 스레드를 격리하여 멀티스레드 작업을 안정적이고 안전하게 수행할 수 있습니다.
자세한 지침은 스레드 안전하지 않은 예: 단일 모델 인스턴스 및 스레드 안전 예제 섹션을 확인하세요.
Python의 전역 인터프리터 잠금(GIL)은 한 번에 하나의 스레드만 Python 바이트코드를 실행하도록 하므로 CPU 바운드 멀티스레드 작업의 성능을 제한할 수 있습니다. 하지만 I/O 바운드 작업이나 YOLO의 기반 C 라이브러리처럼 GIL을 해제하는 라이브러리를 사용하는 프로세스에서는 동시성을 확보할 수 있습니다. 성능을 높이려면 Python의
multiprocessing모듈을 사용한 프로세스 기반 병렬 처리를 고려하세요.Python의 스레딩에 관한 자세한 내용은 Python 스레딩 이해하기 섹션을 참조하세요.
예, Python의
multiprocessing모듈을 사용하면 YOLO 모델 추론을 병렬로 실행할 때 더 안전하고 대체로 효율적입니다. 프로세스 기반 병렬 처리는 별도의 메모리 공간을 생성하여 전역 인터프리터 잠금(GIL)을 피하고 동시성 문제의 위험을 줄입니다. 각 프로세스는 자체 YOLO 모델 인스턴스를 사용하여 독립적으로 작동합니다.YOLO 모델의 프로세스 기반 병렬 처리에 대한 자세한 내용은 스레드 안전 추론 페이지를 참조하세요.