كيفية تنفيذ التوازي باستخدام مكتبة multiprocessing في Python
تمت الكتابة بواسطة: عبد الحكيم
تارخ آخر تحديث: 19 ديسمبر 2024محتوى المقال
- ما هي مكتبة multiprocessing؟
- لماذا نستخدم multiprocessing؟
- إنشاء عملية جديدة
- تمرير المعاملات إلى العمليات
- مشاركة البيانات بين العمليات
- التعامل مع التجمعات (Pools)
- الخاتمة
في العديد من التطبيقات البرمجية، قد نحتاج إلى تنفيذ مهام متعددة في وقت واحد لتحسين الأداء واستغلال موارد المعالجة بشكل أكثر فعالية. مكتبة multiprocessing
في Python تتيح لك تحقيق هذا الهدف من خلال السماح بإنشاء وإدارة عمليات متعددة تعمل بشكل متوازٍ. في هذا المقال، سنتعلم كيفية استخدام multiprocessing
لتنفيذ التوازي في برامج Python.
ما هي مكتبة multiprocessing؟
multiprocessing
هي مكتبة قياسية في Python تُستخدم لإنشاء وإدارة عمليات متعددة (processes). على عكس threading
التي تتيح إنشاء سلاسل عمليات (threads)، فإن multiprocessing
ينشئ عمليات مستقلة تعمل في ذاكرة منفصلة، مما يعني أنه يمكنها الاستفادة الكاملة من أنوية المعالج المتعددة.
لماذا نستخدم multiprocessing؟
في بعض الأحيان، يكون هناك حاجة لتنفيذ مهام ثقيلة حسابيًا والتي قد تستفيد من تشغيلها على أكثر من نواة واحدة من المعالج. في Python، بسبب قيود GIL
(Global Interpreter Lock)، فإن استخدام الخيوط (threads) لا يكون فعالاً في تنفيذ التوازي الحقيقي للمهام. هنا يأتي دور multiprocessing
، حيث يمكنه تنفيذ عمليات متوازية حقيقية عبر أنوية المعالج المختلفة.
إنشاء عملية جديدة
أسهل طريقة لإنشاء عملية جديدة هي استخدام الفئة Process
. سنقوم بإنشاء عملية بسيطة تنفذ دالة معينة:
مثال على إنشاء عملية
لنقم بإنشاء عملية تقوم بطباعة رسالة معينة:
from multiprocessing import Process
def print_message():
print("مرحبًا من العملية!")
# إنشاء العملية
p = Process(target=print_message)
# بدء العملية
p.start()
# انتظار اكتمال العملية
p.join()
في هذا المثال، قمنا بإنشاء عملية جديدة باستخدام الفئة Process
، ومررنا إليها الدالة print_message
لتعمل عند بدء العملية. بعد بدء العملية باستخدام start()
، ننتظر انتهاء العملية باستخدام join()
.
تمرير المعاملات إلى العمليات
يمكنك تمرير المعاملات إلى العملية عن طريق تمريرها إلى الدالة المستهدفة (target function) عند إنشاء العملية. لنفترض أن لدينا دالة تأخذ معاملًا وتطبعه:
def print_square(number):
print(f"مربع {number} هو {number**2}")
# إنشاء عملية جديدة مع تمرير المعامل
p = Process(target=print_square, args=(5,))
# بدء العملية
p.start()
p.join()
في هذا المثال، نقوم بتمرير الرقم 5
إلى الدالة print_square
عند إنشاء العملية. يتم استخدام المعامل args
لتمرير المعاملات على شكل tuple.
مشاركة البيانات بين العمليات
بما أن كل عملية تعمل في مساحة ذاكرة منفصلة، فإن مشاركة البيانات بين العمليات تتطلب استخدام أدوات معينة مثل Queue
، Pipe
، أو استخدام كائنات مشاركة مثل Value
وArray
.
مشاركة البيانات باستخدام Queue
Queue
هي واحدة من أسهل الطرق لمشاركة البيانات بين العمليات. يمكنك استخدام put()
لإضافة بيانات إلى الطابور وget()
لاستخراج البيانات.
from multiprocessing import Process, Queue
def square_numbers(numbers, queue):
for n in numbers:
queue.put(n**2)
# إنشاء الطابور
q = Queue()
# إنشاء العملية
p = Process(target=square_numbers, args=([1, 2, 3, 4], q))
# بدء العملية
p.start()
p.join()
# استخراج البيانات من الطابور
while not q.empty():
print(q.get())
في هذا المثال، نستخدم Queue
لمشاركة نتائج تربيع الأرقام بين العملية الرئيسية والعملية الفرعية. تقوم العملية الفرعية بوضع النتائج في الطابور، بينما تقوم العملية الرئيسية باستخراج النتائج من الطابور بعد انتهاء العملية الفرعية.
مشاركة البيانات باستخدام Value و Array
إذا كنت تحتاج إلى مشاركة بيانات بسيطة مثل الأعداد أو المصفوفات، يمكنك استخدام Value
وArray
اللذان يتيحان لك مشاركة هذه البيانات بين العمليات.
from multiprocessing import Process, Value, Array
def modify_data(num, arr):
num.value += 10
for i in range(len(arr)):
arr[i] *= 2
# إنشاء كائن Value و Array
shared_num = Value('i', 5) # 'i' تعني عدد صحيح
shared_arr = Array('i', [1, 2, 3, 4])
# إنشاء العملية
p = Process(target=modify_data, args=(shared_num, shared_arr))
# بدء العملية
p.start()
p.join()
# عرض القيم المشتركة
print("القيمة المشتركة:", shared_num.value)
print("المصفوفة المشتركة:", shared_arr[:])
في هذا المثال، قمنا بإنشاء كائن Value
يحتوي على عدد صحيح وكائن Array
يحتوي على مصفوفة من الأعداد الصحيحة. ثم قمنا بتمرير هذه الكائنات إلى العملية التي تعدلها. بعد انتهاء العملية، يمكننا عرض القيم المعدلة.
التعامل مع التجمعات (Pools)
إذا كنت تحتاج إلى تنفيذ نفس العملية على مجموعة كبيرة من البيانات، يمكن أن يكون استخدام Pool
أكثر فعالية. تتيح لك Pool
توزيع المهام على عدة عمليات بشكل أوتوماتيكي.
مثال على استخدام Pool
لنقم بإنشاء Pool
من العمليات لمعالجة قائمة من الأرقام وحساب مربعاتها:
from multiprocessing import Pool
def square(n):
return n**2
# إنشاء التجمع
with Pool() as p:
results = p.map(square, [1, 2, 3, 4, 5])
print(results)
في هذا المثال، قمنا بإنشاء Pool
من العمليات واستخدمنا map
لتوزيع عملية حساب مربعات الأرقام على جميع العمليات المتاحة في التجمع.
الخاتمة
تعد مكتبة multiprocessing
أداة قوية في Python لتنفيذ التوازي الحقيقي واستغلال قدرات المعالجات متعددة الأنوية. من خلال إنشاء عمليات مستقلة، مشاركة البيانات بين هذه العمليات، واستخدام التجمعات (Pools)، يمكنك بناء برامج أكثر كفاءة وفعالية في معالجة المهام الثقيلة. نأمل أن يكون هذا المقال قد قدم لك فهماً جيداً لكيفية استخدام multiprocessing
في Python.
طور مهاراتك: مقالات يجب قراءتها في البرمجة
- كيفية كتابة سكربت للتعامل مع API RESTful باستخدام مكتبة requests في Python
- كيفية استخدام مكتبة subprocess لتنفيذ أوامر النظام في Python
- كيفية استخدام مكتبة PyGame لتطوير الألعاب في Python
- كتابة سكربت لتحميل الملفات من الإنترنت باستخدام urllib في Python
- كيفية إنشاء قنوات اتصال باستخدام مكتبة asyncio.Queue في Python
- كيفية استخدام مكتبة boto3 للتفاعل مع خدمات AWS في Python
- كيفية إدارة وتحليل البيانات باستخدام مكتبة Dask في Python
- كيفية التعامل مع ملفات الصوت باستخدام مكتبة pydub في Python
- كيفية إنشاء خريطة موقع Sitemap XML
- كيفية تقسيم النصوص باستخدام دالة split() في Python