Cython: أكثر من 30x تسريع Python Code

بيثون هي اللغة التي يحبها الكثير من المبرمجين. هذه اللغة سهلة الاستخدام بشكل لا يصدق. الشيء هو أن الكود المكتوب في بيثون سهل القراءة وجيد. ومع ذلك ، في المحادثات حول بيثون يمكن للمرء في كثير من الأحيان سماع نفس الشكوى حول هذه اللغة. لا سيما عندما يتحدث خبراء جيم عن بيثون. هكذا يبدو الأمر: "بيثون بطيء". وأولئك الذين يقولون ذلك لا يخطئون ضد الحقيقة.

بالمقارنة مع العديد من لغات البرمجة الأخرى ، فإن بايثون بطيء بالفعل. فيما يلي نتائج الاختبار التي تقارن أداء لغات البرمجة المختلفة في حل المشكلات المختلفة.



هناك عدة طرق لتسريع برامج بيثون. على سبيل المثال ، يمكنك استخدام مكتبات مصممة لاستخدام نوى المعالج متعددة. يُنصح أولئك الذين يعملون مع Numpy أو Pandas أو Scikit-Learn بإلقاء نظرة على حزمة برامج Rapids ، والتي تتيح لك استخدام GPU في العمليات الحسابية العلمية.

كل تقنيات التسريع هذه جيدة في الحالات التي تكون فيها المهام التي يمكن حلها باستخدام بايثون متوازنة. على سبيل المثال ، هذه مهام لمعالجة البيانات الأولية أو العمليات باستخدام المصفوفات.

لكن ماذا لو كان شفرتك نقية بيثون؟ ماذا لو كان لديك حلقة كبيرة يجب أن تستخدمها على الإطلاق ، والتي لا يمكن تنفيذها بالتوازي مع ذلك بسبب حقيقة أن البيانات التي تتم معالجتها يجب معالجتها بالتسلسل؟ هل هناك أي طريقة لتسريع بيثون نفسها؟

يقدم Cython الإجابة على هذا السؤال - وهو مشروع يمكنك من خلاله تسريع التعليمات البرمجية المكتوبة بلغة Python بشكل كبير.

ما هو سيثون؟


Cython ، في جوهره ، هو طبقة وسيطة بين Python و C / C ++. يتيح لك Cython كتابة كود Python منتظم مع بعض التعديلات الطفيفة ، والتي تترجم بعد ذلك مباشرة إلى رمز C.

التغيير الوحيد لرمز Python هو إضافة معلومات حول نوعه لكل متغير. عند كتابة كود Python العادي ، يمكنك إعلان متغير مثل هذا:

 x = 0.5 

عند استخدام Cython عند التصريح عن متغير ، تحتاج إلى تحديد نوعه:

 cdef float x = 0.5 

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

تثبيت Cython بسيط للغاية:

 pip install cython 

أنواع في سيثون


عند استخدام Cython ، يمكن التمييز بين مجموعتين من الأنواع. واحد للمتغيرات ، والثاني هو للوظائف.

إذا كنا نتحدث عن المتغيرات ، فإن الأنواع التالية متاحة لنا:

  • cdef int a, b, c
  • cdef char *s
  • cdef float x = 0.5 (رقم دقة واحدة)
  • cdef double x = 63.4 (رقم الدقة المزدوجة)
  • cdef list names
  • cdef dict goals_for_each_play
  • cdef object card_deck

يرجى ملاحظة أنه هنا ، في الواقع ، يتم عرض أنواع C / C ++!

عند العمل مع الوظائف ، تتوفر الأنواع التالية لنا:

  • def هي وظيفة بيثون منتظمة ، تسمى فقط من بيثون.
  • cdef هي وظيفة Cython لا يمكن استدعاؤها من كود Python العادي. يمكن استدعاء هذه الوظائف فقط داخل كود Cython.
  • cpdef - وظيفة يمكن الوصول إليها من كلا C و Python.

الآن وبعد أن اكتشفنا أنواع Python ، سنتناول سرعة كود Python.

تسريع رمز باستخدام Cython


لنبدأ بإنشاء معيار Python. سيكون هذا بمثابة حلقة يتم فيها حساب عامل الرقم. سيبدو رمز Python النقي المقابل كما يلي:

 def test(x):    y = 1    for i in range(1, x+1):        y *= i    return y 

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

 cpdef int test(int x):    cdef int y = 1    cdef int i    for i in range(1, x+1):        y *= i    return y 

لاحظ أن الوظيفة تحتوي على الكلمة الأساسية cpdef قبلها. هذا يسمح لك باستدعاء هذه الوظيفة من بيثون. بالإضافة إلى ذلك ، يتم تعيين النوع إلى المتغير i ، الذي يلعب دور عداد الحلقة. دعونا لا ننسى أننا بحاجة إلى كتابة جميع المتغيرات المعلنة في الوظيفة. سيسمح هذا للمترجم C بمعرفة أنواع الاستخدام.

قم الآن بإنشاء setup.py ، مما سيساعدنا في تحويل رمز Cython إلى رمز C:

 from distutils.core import setup from Cython.Build import cythonize setup(ext_modules = cythonize('run_cython.pyx')) 

لنجمع:

 python setup.py build_ext --inplace 

رمز C جاهز الآن للاستخدام.

إذا نظرت إلى المجلد الذي يوجد فيه رمز Cython ، يمكنك العثور على جميع الملفات اللازمة لتشغيل الرمز C ، بما في ذلك ملف run_cython.c . إذا كنت مهتمًا ، افتح هذا الملف وانظر إلى رمز C الذي تم إنشاؤه بواسطة Cython.

أنت الآن جاهز لاختبار كود C فائق السرعة. يوجد أدناه الرمز المستخدم لاختبار ومقارنة نسختين من البرنامج.

 import run_python import run_cython import time number = 10 start = time.time() run_python.test(number) end = time.time() py_time = end - start print("Python time = {}".format(py_time)) start = time.time() run_cython.test(number) end = time.time() cy_time = end - start print("Cython time = {}".format(cy_time)) print("Speedup = {}".format(py_time / cy_time)) 

هذا الكود بسيط جدا نحن نستورد الملفات الضرورية - تمامًا مثلما يتم استيراد ملفات Python العادية ، ثم نسميها الوظائف المناظرة ، ونفعلها بنفس الطريقة كما لو كنا سنعمل مع وظائف Python العادية في كل وقت.

ألقِ نظرة على الجدول التالي. قد تلاحظ أن إصدار Cython من البرنامج أسرع من إصدار Python الخاص به في جميع الحالات. كلما كبرت المهمة ، زاد التسارع الذي يوفره Cython.
عدد
بيثون الوقت متري
Cython Time Metric
تسريع النتيجة
10
1.6689300537109375e-06
4.76837158203125e-07
3.5
100
3.337860107421875e-06
4.76837158203125e-07
7.0
1000
2.193450927734375e-05
9.5367431640625e-07
23.0
10000
+0.0002090930938720703
6.4373016357421875e-06
32481
100000
+0.0021562576293945312
6.008148193359375e-05
35.89
1000000
+0.02128767967224121
+0.0005953311920166016
35.75
10000000
+0.2148280143737793
+0.00594782829284668
+36.1187317112278

النتائج


يمكن أن يؤدي استخدام Cython إلى تسريع أي رمز مكتوب بلغة Python تقريبًا ، دون بذل أي جهد خاص. لمزيد من الحلقات في البرنامج والمزيد من البيانات التي يعالجها - النتائج الأفضل التي يمكنك توقعها من Cython.

أعزائي القراء! هل تستخدم Cython في مشاريعك؟

Source: https://habr.com/ru/post/ar462487/


All Articles