0Pricing
Python Academy · درس

أساسيات multiprocessing

استخدم عدة أنوية للمعالج

أساسيات multiprocessing درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.

لماذا multiprocessing؟

يمنع GIL الخيوط من تنفيذ بايت كود Python بالتوازي. وتتجاوز وحدة multiprocessing ذلك من خلال تشغيل عمليات منفصلة، لكل منها مفسّرها الخاص وGIL الخاص بها، ولذلك تُنفَّذ المهام المرتبطة بوحدة المعالجة المركزية فعليًا على عدة أنوية.

import multiprocessing as mp
print('CPU cores available:', mp.cpu_count())

بدء تشغيل عملية

تحاكي Process(target=func) واجهة برمجة التطبيقات الخاصة بالخيوط. استدعوا start() لبدء التشغيل، وjoin() للانتظار.

import multiprocessing as mp

def worker():
    print('hello from a child process')

if __name__ == '__main__':
    p = mp.Process(target=worker)
    p.start()
    p.join()
    print('parent done')

حارس __main__

في بعض المنصات، تستورد العمليات الابنة البرنامج النصي الخاص بكم. ومن دون حارس if __name__ == '__main__':، قد تنشئون عمليات بشكل متكرر. احرصوا دائمًا على وضع رمز التشغيل داخل هذا الحارس.

import multiprocessing as mp

def task(n):
    print('processing', n)

if __name__ == '__main__':
    for i in range(3):
        p = mp.Process(target=task, args=(i,))
        p.start()
        p.join()

تمرير الوسائط

استخدموا args للوسائط الموضعية وkwargs للوسائط المسمّاة، تمامًا كما هو الحال مع الخيوط. تُحوَّل الوسائط إلى pickle وتُرسَل إلى العملية الابنة.

import multiprocessing as mp

def show(label, times):
    for _ in range(times):
        print(label)

if __name__ == '__main__':
    p = mp.Process(target=show, args=('hi',), kwargs={'times': 2})
    p.start()
    p.join()

مجموعة من العاملين

تدير multiprocessing.Pool مجموعة من العمليات. وتوزّع pool.map العناصر القابلة للتكرار بينها، ثم تجمع النتائج بالترتيب.

import multiprocessing as mp

def square(n):
    return n * n

if __name__ == '__main__':
    with mp.Pool(processes=2) as pool:
        print(pool.map(square, range(6)))

ProcessPoolExecutor

توفر واجهة برمجة التطبيقات concurrent.futures أيضًا ProcessPoolExecutor، مع واجهة submit/map نفسها التي رأيتموها مع الخيوط.

from concurrent.futures import ProcessPoolExecutor

def cube(n):
    return n ** 3

if __name__ == '__main__':
    with ProcessPoolExecutor() as ex:
        print(list(ex.map(cube, range(5))))

مساحات ذاكرة منفصلة

لكل عملية ذاكرتها الخاصة. ولا يؤدي تعديل متغير عام في عملية ابنة إلى تغيير نسخته في العملية الأب. يجب إعادة البيانات أو مشاركتها بشكل صريح.

import multiprocessing as mp

counter = 0

def bump():
    global counter
    counter += 100

if __name__ == '__main__':
    p = mp.Process(target=bump)
    p.start()
    p.join()
    print('parent counter still:', counter)

استعادة النتائج

بما أن الذاكرة غير مشتركة، أعيدوا النتائج من خلال Pool.map أو المنفّذات أو قوائم الانتظار بدلًا من تعديل المتغيرات العامة.

import multiprocessing as mp

def double(n):
    return n * 2

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        results = pool.map(double, [1, 2, 3, 4])
    print('results:', results)

apply_async للاستدعاءات الفردية

يجدول apply_async استدعاءً واحدًا ويعيد مقبضًا للنتيجة. استدعوا .get() لاسترداد القيمة.

import multiprocessing as mp

def add(a, b):
    return a + b

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        r = pool.apply_async(add, (3, 4))
        print(r.get())

متطلب Pickle

يجب أن تكون الأهداف والوسائط قابلة للتسلسل باستخدام pickle حتى تتمكن من عبور حدود العمليات. تعمل الدوال المعرّفة في المستوى الأعلى، أما الدوال المجهولة والدوال المحلية فعادةً لا تعمل.

import multiprocessing as mp

def top_level(n):
    return n + 1

if __name__ == '__main__':
    with mp.Pool(2) as pool:
        print(pool.map(top_level, [10, 20]))

متى تستخدمون العمليات

استخدموا العمليات للمهام كثيفة الاستخدام لوحدة المعالجة المركزية، مثل الرياضيات ومعالجة الصور والتحليل. ونظرًا إلى تكلفة إنشاء العمليات وتحويل البيانات إلى pickle، فهي مناسبة لعدد أقل من المهام الأثقل، لا لعدد كبير من المهام الصغيرة جدًا.

import multiprocessing as mp

def heavy(n):
    return sum(i * i for i in range(n))

if __name__ == '__main__':
    with mp.Pool() as pool:
        print(pool.map(heavy, [1000, 2000, 3000]))

تحقق سريع

اختبروا مدى فهمكم لـ multiprocessing.

مراجعة

لقد تعلّمتم أساسيات multiprocessing:

  • تتجاوز العمليات GIL لتحقيق توازٍ حقيقي للمهام المرتبطة بالمعالج.
  • استخدموا الحارس if __name__ == '__main__'.
  • توزّع Pool وProcessPoolExecutor العمل وتجمع النتائج.
  • الذاكرة غير مشتركة، ويجب أن تكون الوسائط قابلة للتسلسل باستخدام pickle.

التالي: مشاركة البيانات بأمان باستخدام قوائم الانتظار والأقفال.

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

هل درس «أساسيات multiprocessing» مجاني؟

نعم — نص درس «أساسيات multiprocessing» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.

ماذا ستتعلم في «أساسيات multiprocessing»؟

استخدم عدة أنوية للمعالج تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟

لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «أساسيات multiprocessing»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟

نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الخيوط وGIL
  2. ThreadPoolExecutor
  3. أساسيات multiprocessing
  4. مشاركة البيانات بأمان
← العودة إلى Python Academy