μ½˜ν…μΈ λ‘œ κ±΄λ„ˆλ›°κΈ°

YOLO λͺ¨λΈμ„ μ‚¬μš©ν•œ μŠ€λ ˆλ“œ μ•ˆμ „ μΆ”λ‘ 

λ©€ν‹° μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œ YOLO λͺ¨λΈμ„ μ‹€ν–‰ν•˜λ €λ©΄ μŠ€λ ˆλ“œ μ•ˆμ „μ„ 보μž₯ν•˜κΈ° μœ„ν•΄ μ‹ μ€‘ν•œ κ³ λ €κ°€ ν•„μš”ν•©λ‹ˆλ‹€. Python's threading λͺ¨λ“ˆμ„ μ‚¬μš©ν•˜λ©΄ μ—¬λŸ¬ μŠ€λ ˆλ“œλ₯Ό λ™μ‹œμ— μ‹€ν–‰ν•  수 μžˆμ§€λ§Œ μ΄λŸ¬ν•œ μŠ€λ ˆλ“œμ—μ„œ YOLO λͺ¨λΈμ„ μ‚¬μš©ν•  λ•ŒλŠ” μ£Όμ˜ν•΄μ•Ό ν•  μ€‘μš”ν•œ μ•ˆμ „ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 νŽ˜μ΄μ§€μ—μ„œλŠ” μŠ€λ ˆλ“œμ— μ•ˆμ „ν•œ YOLO λͺ¨λΈ 좔둠을 λ§Œλ“œλŠ” 방법을 μ•ˆλ‚΄ν•©λ‹ˆλ‹€.

Python μŠ€λ ˆλ”© 이해

Python μŠ€λ ˆλ“œλŠ” ν”„λ‘œκ·Έλž¨μ—μ„œ ν•œ λ²ˆμ— μ—¬λŸ¬ μž‘μ—…μ„ μ‹€ν–‰ν•  수 μžˆλŠ” 병렬 처리의 ν•œ ν˜•νƒœμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ Python 의 κΈ€λ‘œλ²Œ 인터프리터 잠금(GIL)은 ν•œ λ²ˆμ— ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œλ§Œ Python λ°”μ΄νŠΈμ½”λ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.

μ‹±κΈ€ μŠ€λ ˆλ“œμ™€ λ©€ν‹° μŠ€λ ˆλ“œ μ˜ˆμ‹œ

μ΄λŠ” μ œν•œ μ‚¬ν•­μ²˜λŸΌ λ“€λ¦¬μ§€λ§Œ, μŠ€λ ˆλ“œλŠ” 특히 I/O 바인딩 μ—°μ‚°μ΄λ‚˜ YOLO 의 κΈ°λ³Έ C λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μˆ˜ν–‰ν•˜λŠ” 것과 같이 GIL을 ν•΄μ œν•˜λŠ” 연산을 μ‚¬μš©ν•  λ•Œ λ™μ‹œμ„±μ„ μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

곡유 λͺ¨λΈ μΈμŠ€ν„΄μŠ€μ˜ μœ„ν—˜μ„±

YOLO λͺ¨λΈμ„ μŠ€λ ˆλ“œ μ™ΈλΆ€μ—μ„œ μΈμŠ€ν„΄μŠ€ν™”ν•˜κ³  이 μΈμŠ€ν„΄μŠ€λ₯Ό μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ κ³΅μœ ν•˜λ©΄ λ™μ‹œ μ•‘μ„ΈμŠ€λ‘œ 인해 λͺ¨λΈμ˜ λ‚΄λΆ€ μƒνƒœκ°€ 일관성 없이 μˆ˜μ •λ˜λŠ” 경쟁 쑰건이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” λͺ¨λΈ λ˜λŠ” κ·Έ ꡬ성 μš”μ†Œκ°€ μŠ€λ ˆλ“œμ— μ•ˆμ „ν•˜μ§€ μ•Šλ„λ‘ μ„€κ³„λ˜μ§€ μ•Šμ€ μƒνƒœλ₯Ό λ³΄μœ ν•  λ•Œ 특히 λ¬Έμ œκ°€ λ©λ‹ˆλ‹€.

μŠ€λ ˆλ“œ μ•ˆμ „ν•˜μ§€ μ•Šμ€ 예제: 단일 λͺ¨λΈ μΈμŠ€ν„΄μŠ€

Python μ—μ„œ μŠ€λ ˆλ“œλ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” λ™μ‹œμ„± 문제λ₯Ό μΌμœΌν‚¬ 수 μžˆλŠ” νŒ¨ν„΄μ„ μΈμ‹ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€. 단일 YOLO λͺ¨λΈ μΈμŠ€ν„΄μŠ€λ₯Ό μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ κ³΅μœ ν•˜λŠ” 것은 ν”Όν•΄μ•Ό ν•©λ‹ˆλ‹€.

# Unsafe: Sharing a single model instance across threads
from ultralytics import YOLO
from threading import Thread

# Instantiate the model outside the thread
shared_model = YOLO("yolov8n.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 ultralytics import YOLO
from threading import Thread

# Instantiate multiple models outside the thread
shared_model_1 = YOLO("yolov8n_1.pt")
shared_model_2 = YOLO("yolov8n_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()

두 개의 κ°œλ³„ λͺ¨λΈ μΈμŠ€ν„΄μŠ€κ°€ μžˆλ”λΌλ„ λ™μ‹œμ„± 문제의 μœ„ν—˜μ€ μ—¬μ „νžˆ μ‘΄μž¬ν•©λ‹ˆλ‹€. λ‚΄λΆ€ κ΅¬ν˜„μ—μ„œ YOLO λŠ” μŠ€λ ˆλ“œ μ•ˆμ „ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ λ³„λ„μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄ 특히 μ΄λŸ¬ν•œ μΈμŠ€ν„΄μŠ€κ°€ μŠ€λ ˆλ“œ 둜컬이 μ•„λ‹Œ κΈ°λ³Έ λ¦¬μ†ŒμŠ€λ‚˜ μƒνƒœλ₯Ό κ³΅μœ ν•˜λŠ” 경우 경쟁 쑰건을 λ°©μ§€ν•˜μ§€ λͺ»ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μŠ€λ ˆλ“œ μ•ˆμ „ μΆ”λ‘ 

μŠ€λ ˆλ“œ μ•ˆμ „ 좔둠을 μˆ˜ν–‰ν•˜λ €λ©΄ 각 μŠ€λ ˆλ“œ 내에 λ³„λ„μ˜ YOLO λͺ¨λΈμ„ μΈμŠ€ν„΄μŠ€ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ 각 μŠ€λ ˆλ“œκ°€ 고유의 격리된 λͺ¨λΈ μΈμŠ€ν„΄μŠ€λ₯Ό κ°–κ²Œ λ˜μ–΄ 경쟁 쑰건의 μœ„ν—˜μ„ μ œκ±°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μŠ€λ ˆλ“œ μ•ˆμ „ 예제

μ•ˆμ „ν•œ 병렬 좔둠을 μœ„ν•΄ 각 μŠ€λ ˆλ“œ λ‚΄μ—μ„œ YOLO λͺ¨λΈμ„ μΈμŠ€ν„΄μŠ€ν™”ν•˜λŠ” 방법은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

# Safe: Instantiating a single model inside each thread
from ultralytics import YOLO
from threading import Thread


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("yolov8n.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 μΈμŠ€ν„΄μŠ€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ–΄λ–€ μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œμ˜ λͺ¨λΈ μƒνƒœλ₯Ό κ°„μ„­ν•˜μ§€ λͺ»ν•˜λ―€λ‘œ 각 μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ μŠ€λ ˆλ“œμ™€ 예기치 μ•Šμ€ μƒν˜Έ μž‘μš© 없이 μ•ˆμ „ν•˜κ²Œ 좔둠을 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ²°λ‘ 

YOLO λͺ¨λΈκ³Ό Python threadingλ₯Ό μ‚¬μš©ν•˜λ©΄ μŠ€λ ˆλ“œ μ•ˆμ „μ„ 보μž₯ν•˜κΈ° μœ„ν•΄ 항상 λͺ¨λΈμ„ μ‚¬μš©ν•  μŠ€λ ˆλ“œ λ‚΄μ—μ„œ λͺ¨λΈμ„ μΈμŠ€ν„΄μŠ€ν™”ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ 경쟁 쑰건을 ν”Όν•˜κ³  μΆ”λ‘  μž‘μ—…μ„ μ•ˆμ •μ μœΌλ‘œ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

보닀 κ³ κΈ‰ μ‹œλ‚˜λ¦¬μ˜€μ™€ λ©€ν‹°μŠ€λ ˆλ“œ μΆ”λ‘  μ„±λŠ₯을 λ”μš± μ΅œμ ν™”ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같이 ν”„λ‘œμ„ΈμŠ€ 기반 병렬 처리λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. multiprocessing λ˜λŠ” μ „μš© μž‘μ—…μž ν”„λ‘œμ„ΈμŠ€κ°€ μžˆλŠ” μž‘μ—… λŒ€κΈ°μ—΄μ„ ν™œμš©ν•˜μ„Έμš”.



생성 2023-11-12, μ—…λ°μ΄νŠΈ 2024-05-03
μž‘μ„±μž: glenn-jocher (2)

λŒ“κΈ€