Ultralytics YOLO27:
Get Started

استدلال آمن لمؤشرات الترابط باستخدام نماذج YOLO#

لتشغيل الاستدلال باستخدام Ultralytics YOLO بأمان عبر مؤشرات ترابط Python، أنشئ نموذجًا منفصلًا YOLO داخل كل مؤشر ترابط بدلًا من مشاركة مثيل واحد بينها. تؤدي مشاركة نموذج واحد إلى حالات تسابق تُفسد حالته الداخلية وتنتج نتائج غير متوقعة، لأن وحدة threading في Python تشغّل مؤشرات الترابط بالتزامن على الكائن نفسه. يشرح هذا الدليل سبب فشل المشاركة، ويعرض النمط الآمن لكل مؤشر ترابط، ويتناول المزيّن ThreadingLocked للحالات التي يتعين فيها مشاركة مثيل.

انتقل إلى سبب فشل مشاركة النموذج، أو النمط الآمن لمؤشرات الترابط، أو المزيّن ThreadingLocked.



شاهد: كيفية تنفيذ استدلال آمن مع الخيوط باستخدام نماذج Ultralytics YOLO في Python | تعدد الخيوط 🚀

فهم مؤشرات ترابط Python#

مؤشرات ترابط Python شكل من أشكال التوازي يتيح لبرنامجك تنفيذ عمليات متعددة في الوقت نفسه. لكن قفل المفسّر العام (GIL) في Python يعني أنه لا يمكن إلا لمؤشر ترابط واحد تنفيذ شيفرة Python الثنائية في كل مرة.

Single-thread vs multi-thread inference

على الرغم من أن ذلك يبدو قيدًا، فإن مؤشرات الترابط لا تزال تتيح التزامن، ولا سيما في العمليات المحدودة بالإدخال/الإخراج أو عند استخدام عمليات تحرّر GIL، مثل العمليات التي تنفذها مكتبات YOLO الأساسية المكتوبة بلغة C.

مخاطر مشاركة مثيلات النماذج#

قد يؤدي إنشاء نموذج 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 مع threading في Python، خصّص لكل مؤشر ترابط مثيل نموذج مستقلًا، ولا تشارك مثيلًا واحدًا مطلقًا بين مؤشرات الترابط. ويُعد إنشاء النموذج داخل مؤشر الترابط الذي يستخدمه أبسط طريقة لضمان ذلك، وتجنّب حالات التسابق والحفاظ على موثوقية مهام الاستدلال.

للسيناريوهات الأكثر تقدمًا ولتحسين أداء الاستدلال متعدد مؤشرات الترابط، فكّر في استخدام التوازي القائم على العمليات عبر multiprocessing، أو الاستفادة من قائمة انتظار مهام مع عمليات عاملة مخصصة.

الأسئلة الشائعة#

  • لتجنّب حالات التسابق عند استخدام نماذج Ultralytics YOLO في بيئة Python متعددة مؤشرات الترابط، أنشئ نموذج 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.

  • لتشغيل استدلال نماذج YOLO بأمان باستخدام مؤشرات ترابط متعددة في Python، اتبع أفضل الممارسات التالية:

    1. أنشئ نماذج YOLO داخل كل مؤشر ترابط بدلًا من مشاركة مثيل نموذج واحد بين مؤشرات الترابط.
    2. استخدم وحدة multiprocessing في Python للمعالجة المتوازية، لتجنّب المشكلات المرتبطة بقفل المفسّر العام (GIL).
    3. تذكّر أن مكتبات C الأساسية في YOLO (PyTorch وOpenCV) تحرّر GIL تلقائيًا أثناء العمليات الحسابية المكثفة، لذا تظل مؤشرات الترابط قادرة على تشغيل الاستدلال بالتزامن.
    4. فكّر في استخدام المزيّن 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 خاص به لتجنّب حالات التسابق. فعندما يُشارك مثيل نموذج واحد بين مؤشرات ترابط متعددة، قد يؤدي الوصول المتزامن إلى سلوك غير متوقع وتغييرات في الحالة الداخلية للنموذج. ويضمن استخدام مثيلات منفصلة عزل مؤشرات الترابط، ما يجعل مهامك متعددة مؤشرات الترابط موثوقة وآمنة.

    للحصول على إرشادات مفصّلة، راجع قسمي مثال غير آمن لمؤشرات الترابط: مثيل نموذج واحد ومثال آمن لمؤشرات الترابط.

  • لا يسمح قفل المفسّر العام (GIL) في Python إلا لمؤشر ترابط واحد بتنفيذ شيفرة Python الثنائية في كل مرة، ما قد يحد من أداء المهام متعددة مؤشرات الترابط والمقيّدة بوحدة CPU. لكن يمكنك تحقيق التزامن في العمليات المحدودة بالإدخال/الإخراج أو العمليات التي تستخدم مكتبات تحرّر GIL، مثل مكتبات C الأساسية في YOLO. لتحسين الأداء، فكّر في استخدام التوازي القائم على العمليات عبر وحدة multiprocessing في Python.

    لمزيد من المعلومات حول مؤشرات الترابط في Python، راجع قسم فهم مؤشرات ترابط Python.

  • نعم، يُعد استخدام وحدة multiprocessing في Python أكثر أمانًا وغالبًا أكثر كفاءة لتشغيل استدلال نماذج YOLO بالتوازي. ينشئ التوازي القائم على العمليات مساحات ذاكرة منفصلة، ما يتجاوز قفل المفسّر العام (GIL) ويقلل خطر مشكلات التزامن. وتعمل كل عملية بشكل مستقل باستخدام مثيل نموذج YOLO خاص بها.

    لمزيد من التفاصيل حول التوازي القائم على العمليات مع نماذج YOLO، راجع صفحة الاستدلال الآمن لمؤشرات الترابط.

التعليقات