أفضل ممارسات Cython والاتفاقيات والمعرفة#
يوثق هذا النصائح لتطوير كود Cython في scikit-learn.
نصائح للتطوير باستخدام Cython في scikit-learn#
نصائح لتسهيل التطوير#
الوقت الذي تقضيه في قراءة وثائق Cython ليس وقتًا ضائعًا.
إذا كنت تنوي استخدام OpenMP: في نظام MacOS، لا يُنفِّذ توزيع النظام
clang
لـ OpenMP. يمكنك تثبيت حزمةcompilers
المتاحة علىconda-forge
التي تأتي مع تنفيذ OpenMP.قد يساعد تنشيط الفحوصات. على سبيل المثال، لتنشيط boundscheck، استخدم:
export SKLEARN_ENABLE_DEBUG_CYTHON_DIRECTIVES=1
ابدأ من الصفر في دفتر ملاحظات لفهم كيفية استخدام Cython والحصول على تعليقات على عملك بسرعة. إذا كنت تخطط لاستخدام OpenMP لعمليات التنفيذ الخاصة بك في Jupyter Notebook، فقم بإضافة وسيطات مترجم ورابط إضافية في Cython magic.
# لـ GCC و clang %%cython --compile-args=-fopenmp --link-args=-fopenmp # لمترجمات Microsoft %%cython --compile-args=/openmp --link-args=/openmp
لتصحيح أخطاء كود C (على سبيل المثال، segfault)، استخدم
gdb
مع:gdb --ex r --args python ./entrypoint_to_bug_reproducer.py
للوصول إلى بعض القيمة في مكانها لتصحيح الأخطاء في سياق
cdef (nogil)
، استخدم:with gil: print(state_to_print)
لاحظ أن Cython لا يمكنه تحليل سلاسل f مع تعبيرات
{var=}
، على سبيل المثالprint(f"{test_val=}")
تحتوي قاعدة كود scikit-learn على الكثير من تعريفات (إعادة تعريفات) الأنواع غير الموحدة (المدمجة). هناك حاليًا عمل جارٍ لتبسيط ذلك وتوحيده عبر قاعدة التعليمات البرمجية. في الوقت الحالي، تأكد من فهمك للأنواع الملموسة التي يتم استخدامها في النهاية.
قد تجد هذا الاسم المستعار لتجميع ملحق Cython الفردي مفيدًا:
# قد ترغب في إضافة هذا الاسم المستعار إلى تكوين البرنامج النصي shell الخاص بك. alias cythonX="cython -X language_level=3 -X boundscheck=False -X wraparound=False -X initializedcheck=False -X nonecheck=False -X cdivision=True" # يقوم هذا بإنشاء `source.c` كما لو كنت قد قمت بإعادة تجميع scikit-learn بالكامل. cythonX --annotate source.pyx
يسمح استخدام خيار
--annotate
مع هذا العلم بإنشاء تقرير HTML لتعليق توضيحي للتعليمات البرمجية. يشير هذا التقرير إلى التفاعلات مع مترجم CPython على أساس كل سطر على حدة. يجب تجنب التفاعلات مع مترجم CPython قدر الإمكان في الأقسام كثيفة الحساب للخوارزميات. لمزيد من المعلومات، يرجى الرجوع إلى هذا القسم من برنامج Cython التعليمي# يقوم هذا بإنشاء تقرير HTML (`source.html`) لـ `source.c`. cythonX --annotate source.pyx
نصائح للأداء#
افهم GIL في سياق CPython (المشكلات التي يحلها، وما هي حدوده) واحصل على فهم جيد لوقت تعيين Cython إلى كود C خالٍ من التفاعلات مع CPython، ومتى لن يتم ذلك، ومتى لا يمكن ذلك (على سبيل المثال، وجود تفاعلات مع كائنات Python، والتي تتضمن دوال). في هذا الصدد، يوفر PEP073 نظرة عامة جيدة وسياقًا ومسارات للإزالة.
تأكد من أنك قمت بإلغاء تنشيط الفحوصات.
فضّل دائمًا عروض الذاكرة على
cnp.ndarray
كلما أمكن ذلك: عروض الذاكرة خفيفة الوزن.تجنب تقسيم عروض الذاكرة: قد يكون تقسيم عروض الذاكرة مكلفًا أو مضللًا في بعض الحالات ومن الأفضل عدم استخدامه، حتى لو كان التعامل مع أبعاد أقل في بعض السياقات أمرًا مفضلًا.
زيِّن الفئات أو الأساليب النهائية بـ
@final
(يسمح هذا بإزالة الجداول الافتراضية عند الحاجة)دوال وأساليب مضمنة عندما يكون ذلك منطقيًا
في حالة الشك، اقرأ كود C أو C++ الذي تم إنشاؤه إذا استطعت: "كلما قل عدد تعليمات C والتوجيهات غير المباشرة لسطر كود Cython، كان ذلك أفضل" هي قاعدة جيدة.
إعلانات
nogil
هي مجرد تلميحات: عند الإعلان عن دوالcdef
على أنها nogil، فهذا يعني أنه يمكن استدعاؤها دون الاحتفاظ بـ GIL، لكنها لا تُطلِق GIL عند الدخول إليها. عليك أن تفعل ذلك بنفسك إما عن طريق تمريرnogil=True
إلىcython.parallel.prange
صراحةً، أو باستخدام مدير سياق صريح:cdef inline void my_func(self) nogil: # بعض المنطق الذي يتفاعل مع CPython، على سبيل المثال تخصيص مصفوفات عبر NumPy. with nogil: # يتم تشغيل الكود هنا كما لو كان مكتوبًا بلغة C. return 0
يعتمد هذا العنصر على هذا التعليق من Stéfan Benhel
يمكن إجراء استدعاءات مباشرة لإجراءات BLAS عبر واجهات مُعرَّفة في
sklearn.utils._cython_blas
.
استخدام OpenMP#
نظرًا لأنه يمكن بناء scikit-learn بدون OpenMP، فمن الضروري حماية كل استدعاء مباشر لـ OpenMP.
توفر وحدة _openmp_helpers
، المتاحة في
sklearn/utils/_openmp_helpers.pyx
إصدارات محمية من إجراءات OpenMP. لاستخدام إجراءات OpenMP، يجب
cimported
من هذه الوحدة وليس من مكتبة OpenMP مباشرةً:
from sklearn.utils._openmp_helpers cimport omp_get_max_threads
max_threads = omp_get_max_threads()
حلقات التكرار المتوازية، prange
، محمية بالفعل بواسطة cython ويمكن استخدامها مباشرةً
من cython.parallel
.
الأنواع#
يتطلب كود Cython استخدام أنواع صريحة. هذا أحد أسباب حصولك على
زيادة في الأداء. لتجنب ازدواجية التعليمات البرمجية، لدينا مكان مركزي
للأنواع الأكثر استخدامًا في
sklearn/utils/_typedefs.pyd.
من الناحية المثالية، تبدأ بإلقاء نظرة هناك و cimport
الأنواع التي تحتاجها، على سبيل المثال
from sklear.utils._typedefs cimport float32, float64