تحسين كود بايثون باستخدام أدوات التنميط
إعداد Google Colab للعمل على تحسين كود Python باستخدام أدوات التوصيف، نبدأ بإعداد بيئة Google Colab. إذا كنا جديدًا على Colab، فهي منصة سحابية أساسية وقوية توفر الوصول إلى دفاتر ملاحظات Jupyter ومجموعة من مكتبات Python. يمكننا الوصول إلى Colab من خلال زيارة (https://colab.research.google.com/) وإنشاء دفتر ملاحظات Python جديد.
استيراد مكتبات ملفات التعريف
يعتمد تحسيننا على الاستخدام الكفء لمكتبات ملفات التعريف. مكتبتان مهمتان في هذا السياق هما cProfile وline_profiler.
يستورد cProfile
يستورد line_profiler
مكتبة 'cProfile' هي أداة مدمجة في لغة Python لتحليل التعليمات البرمجية، في حين أن 'line_profiler' عبارة عن حزمة خارجية تسمح لنا بالتعمق أكثر، وتحليل التعليمات البرمجية سطرًا تلو الآخر.
في هذه الخطوة، نقوم بإنشاء نموذج لبرنامج Python لحساب تسلسل فيبوناتشي باستخدام دالة متكررة. دعونا نحلل هذه العملية بمزيد من التعمق. تسلسل فيبوناتشي عبارة عن مجموعة من الأرقام حيث يكون كل رقم متتالي هو مجموع الرقمين اللذين يسبقانه. يبدأ عادة بـ 0 و1، لذا يبدو التسلسل مثل 0، 1، 1، 2، 3، 5، 8، 13، 21، وهكذا. إنه تسلسل رياضي شائع الاستخدام كمثال في البرمجة نظرًا لطبيعته العودية.
نحدد دالة بايثون تسمى 'فيبوناتشي' في دالة فيبوناتشي العودية. تأخذ هذه الدالة عددًا صحيحًا 'n' كوسيطة لها، وهو ما يمثل الموضع في تسلسل فيبوناتشي الذي نريد حسابه. نريد تحديد موقع الرقم الخامس في تسلسل فيبوناتشي، على سبيل المثال، إذا كان 'n' يساوي 5.
مواطنه فيبوناتشي ( ن ) :
بعد ذلك، نقوم بإنشاء حالة أساسية. الحالة الأساسية في العودية هي سيناريو ينهي الاستدعاءات ويعيد قيمة محددة مسبقًا. في تسلسل فيبوناتشي، عندما يكون 'n' هو 0 أو 1، فإننا نعرف النتيجة بالفعل. أرقام فيبوناتشي 0 و1 هي 0 و1 على التوالي.
لو ن <= 1 :يعود ن
تحدد عبارة 'if' ما إذا كانت 'n' أقل من أو تساوي 1. إذا كانت كذلك، فإننا نعيد 'n' نفسها، حيث لا توجد حاجة لمزيد من التكرار.
حساب العودية
إذا تجاوزت 'n' 1، فإننا نواصل الحساب العودي. في هذه الحالة، نحتاج إلى العثور على رقم فيبوناتشي 'n' من خلال جمع أرقام فيبوناتشي '(n-1)' و'(n-2)'. نحقق ذلك عن طريق إجراء مكالمتين متكررتين داخل الوظيفة.
آخر :يعود فيبوناتشي ( ن - 1 ) + فيبوناتشي ( ن - 2 )
هنا، 'fibonacci(n – 1)' يحسب '(n-1)' رقم فيبوناتشي، و'fibonacci(n - 2)' يحسب '(n-2)' رقم فيبوناتشي. نضيف هاتين القيمتين للحصول على رقم فيبوناتشي المطلوب عند الموضع 'n'.
باختصار، تقوم دالة 'فيبوناتشي' هذه بحساب أرقام فيبوناتشي بشكل متكرر عن طريق تقسيم المشكلة إلى مسائل فرعية أصغر. يقوم بإجراء مكالمات متكررة حتى يصل إلى الحالات الأساسية (0 أو 1)، ويعيد القيم المعروفة. بالنسبة لأي 'n' آخر، يتم حساب رقم فيبوناتشي عن طريق جمع نتائج نداءين متكررين لـ '(n-1)' و'(n-2)'.
في حين أن هذا التنفيذ سهل لحساب أرقام فيبوناتشي، إلا أنه ليس الأكثر كفاءة. في الخطوات اللاحقة، سنستخدم أدوات التوصيف لتحديد وتحسين قيود الأداء الخاصة به للحصول على أوقات تنفيذ أفضل.
تعريف الرمز باستخدام CProfile
الآن، نقوم بتعريف وظيفة 'فيبوناتشي' الخاصة بنا من خلال استخدام 'cProfile'. يوفر تمرين التوصيف هذا نظرة ثاقبة على الوقت الذي يستغرقه كل استدعاء دالة.
com.cprofiler = cProfile. حساب تعريفي ( )com.cprofiler. يُمكَِن ( )
نتيجة = فيبوناتشي ( 30 )
com.cprofiler. إبطال ( )
com.cprofiler. print_stats ( نوع = 'تراكمي' )
في هذا المقطع، نقوم بتهيئة كائن 'cProfile'، وتنشيط التوصيف، وطلب وظيفة 'fibonacci' بـ 'n=30'، وإلغاء تنشيط التوصيف، وعرض الإحصائيات التي تم فرزها حسب الوقت التراكمي. يمنحنا هذا التصنيف الأولي نظرة عامة عالية المستوى حول الوظائف التي تستهلك معظم الوقت.
! تثبيت النقطة line_profilerيستورد cProfile
يستورد line_profiler
مواطنه فيبوناتشي ( ن ) :
لو ن <= 1 :
يعود ن
آخر :
يعود فيبوناتشي ( ن - 1 ) + فيبوناتشي ( ن - 2 )
com.cprofiler = cProfile. حساب تعريفي ( )
com.cprofiler. يُمكَِن ( )
نتيجة = فيبوناتشي ( 30 )
com.cprofiler. إبطال ( )
com.cprofiler. print_stats ( نوع = 'تراكمي' )
لتكوين ملف تعريف للتعليمات البرمجية سطرًا تلو الآخر باستخدام line_profiler للحصول على تحليل أكثر تفصيلاً، نستخدم 'line_profiler' لتقسيم التعليمات البرمجية الخاصة بنا سطرًا تلو الآخر. قبل استخدام 'line_profiler'، يجب علينا تثبيت الحزمة في مستودع Colab.
! تثبيت النقطة line_profilerالآن بعد أن أصبح لدينا 'line_profiler' جاهزًا، يمكننا تطبيقه على دالة 'fibonacci':
%load_ext line_profilerمواطنه فيبوناتشي ( ن ) :
لو ن <= 1 :
يعود ن
آخر :
يعود فيبوناتشي ( ن - 1 ) + فيبوناتشي ( ن - 2 )
%lprun -f فيبوناتشي فيبوناتشي ( 30 )
يبدأ هذا المقتطف بتحميل الامتداد 'line_profiler'، ويحدد وظيفة 'fibonacci'، ويستخدم أخيرًا '%lprun' لتعريف وظيفة 'fibonacci' بـ 'n=30'. فهو يوفر تقسيمًا لأوقات التنفيذ سطرًا تلو الآخر، مما يوضح بدقة أين ينفق الكود الخاص بنا موارده.
بعد تشغيل أدوات التوصيف لتحليل النتائج، سيتم تقديمها مع مجموعة من الإحصائيات التي توضح خصائص أداء الكود الخاص بنا. تتضمن هذه الإحصائيات إجمالي الوقت المستغرق في كل وظيفة ومدة كل سطر من التعليمات البرمجية. على سبيل المثال، يمكننا أن نميز أن دالة فيبوناتشي تستثمر قدرًا أكبر قليلاً من الوقت في إعادة حساب القيم المتطابقة عدة مرات. هذا هو الحساب الزائد وهو مجال واضح حيث يمكن تطبيق التحسين، إما من خلال الحفظ أو عن طريق استخدام الخوارزميات التكرارية.
الآن، نقوم بإجراء تحسينات حيث حددنا تحسينًا محتملاً في دالة فيبوناتشي الخاصة بنا. لاحظنا أن الدالة تعيد حساب نفس أرقام فيبوناتشي عدة مرات، مما يؤدي إلى تكرار غير ضروري وبطء وقت التنفيذ.
لتحسين ذلك، نقوم بتنفيذ الحفظ. الحفظ هو أسلوب تحسين يتضمن تخزين النتائج المحسوبة مسبقًا (في هذه الحالة، أرقام فيبوناتشي) وإعادة استخدامها عند الحاجة بدلاً من إعادة حسابها. وهذا يقلل من الحسابات الزائدة ويحسن الأداء، خاصة بالنسبة للوظائف العودية مثل تسلسل فيبوناتشي.
لتنفيذ الحفظ في دالة فيبوناتشي لدينا، نكتب الكود التالي:
# قاموس لتخزين أرقام فيبوناتشي المحسوبةfib_cache = { }
مواطنه فيبوناتشي ( ن ) :
لو ن <= 1 :
يعود ن
# تحقق مما إذا كانت النتيجة مخزنة مؤقتًا بالفعل
لو ن في fib_cache:
يعود fib_cache [ ن ]
آخر :
# حساب وتخزين النتيجة
fib_cache [ ن ] = فيبوناتشي ( ن - 1 ) + فيبوناتشي ( ن - 2 )
يعود fib_cache [ ن ] ,
في هذه النسخة المعدلة من دالة 'فيبوناتشي'، نقدم قاموس 'fib_cache' لتخزين أرقام فيبوناتشي المحسوبة مسبقًا. قبل حساب رقم فيبوناتشي، نتحقق مما إذا كان موجودًا بالفعل في ذاكرة التخزين المؤقت. إذا كان الأمر كذلك، فإننا نعيد النتيجة المخزنة مؤقتًا. في أي حالة أخرى، نقوم بحسابها، ونحتفظ بها في ذاكرة التخزين المؤقت، ثم نعيدها.
تكرار التنميط والتحسين
بعد تنفيذ التحسين (الحفظ في حالتنا)، من المهم تكرار عملية التوصيف لمعرفة تأثير تغييراتنا والتأكد من أننا قمنا بتحسين أداء الكود.
التنميط بعد التحسين
يمكننا استخدام نفس أدوات التنميط، 'cProfile' و'line_profiler'، لتعريف دالة فيبوناتشي المحسنة. ومن خلال مقارنة نتائج التنميط الجديدة مع النتائج السابقة، يمكننا قياس فعالية التحسين الذي قمنا به.
إليك كيفية تحديد وظيفة 'فيبوناتشي' المحسنة باستخدام 'cProfile':
com.cprofiler = cProfile. حساب تعريفي ( )com.cprofiler. يُمكَِن ( )
نتيجة = فيبوناتشي ( 30 )
com.cprofiler. إبطال ( )
com.cprofiler. print_stats ( نوع = 'تراكمي' )
باستخدام 'line_profiler'، نقوم بتوصيفه سطرًا تلو الآخر:
%lprun -f فيبوناتشي فيبوناتشي ( 30 )شفرة:
# قاموس لتخزين أرقام فيبوناتشي المحسوبةfib_cache = { }
مواطنه فيبوناتشي ( ن ) :
لو ن <= 1 :
يعود ن
# تحقق مما إذا كانت النتيجة مخزنة مؤقتًا بالفعل
لو ن في fib_cache:
يعود fib_cache [ ن ]
آخر :
# حساب وتخزين النتيجة
fib_cache [ ن ] = فيبوناتشي ( ن - 1 ) + فيبوناتشي ( ن - 2 )
يعود fib_cache [ ن ]
com.cprofiler = cProfile. حساب تعريفي ( )
com.cprofiler. يُمكَِن ( )
نتيجة = فيبوناتشي ( 30 )
com.cprofiler. إبطال ( )
com.cprofiler. print_stats ( نوع = 'تراكمي' )
%lprun -f فيبوناتشي فيبوناتشي ( 30 )
لتحليل نتائج التوصيف بعد التحسين، سيتم تقليل أوقات التنفيذ بشكل كبير، خاصة بالنسبة لقيم 'n' الكبيرة. بسبب الحفظ، نلاحظ أن الدالة الآن تقضي وقتًا أقل بكثير في إعادة حساب أرقام فيبوناتشي.
هذه الخطوات ضرورية في عملية التحسين. يتضمن التحسين إجراء تغييرات مدروسة على التعليمات البرمجية الخاصة بنا بناءً على الملاحظات التي تم الحصول عليها من التوصيف، بينما يضمن تكرار التوصيف أن تحسيناتنا تؤدي إلى تحسينات الأداء المتوقعة. من خلال التنميط التكراري والتحسين والتحقق من الصحة، يمكننا ضبط كود Python الخاص بنا لتقديم أداء أفضل وتعزيز تجربة المستخدم لتطبيقاتنا.
خاتمة
في هذه المقالة، ناقشنا المثال الذي قمنا فيه بتحسين كود Python باستخدام أدوات التنميط داخل بيئة Google Colab. لقد قمنا بتهيئة المثال من خلال الإعداد، واستوردنا مكتبات ملفات التعريف الأساسية، وكتبنا نماذج الأكواد، وقمنا بتوصيفها باستخدام كل من 'cProfile' و'line_profiler'، وحسبنا النتائج، وقمنا بتطبيق التحسينات، وقمنا بتحسين أداء الكود بشكل متكرر.