Cython و افزایش ۳۰ برابری سرعت پایتون — راهنمای کاربردی
پایتون یک زبان برنامهنویسی مورد علاقه عموم است. پایتون با اختلاف زیادی یکی از سادهترین زبانهای برنامهنویسی است، زیرا کدنویسی آن تا حدود زیادی به روش شهودی و خوانا برای انسان صورت میپذیرد. با این حال در اغلب موارد شکایتهایی به خصوص از سوی طرفداران زبان C میبینیم که پایتون کُند است و البته ادعای نابجایی هم نیست. راه حل مشکل در ابزاری به نام Cython است.
پایتون در قیاس با بسیاری از زبانهای دیگر برنامهنویسی کند است. وبسایت Benchmark Game (+) بنچمارکهایی برای مقایسه سرعت زبانهای محبوب برنامهنویسی در هنگام اجرای وظایف گوناگون ارائه کرده است. روشهای مختلفی برای افزایش سرعت کدهای پایتون وجود دارد که برخی از آنها شامل موارد زیر هستند:
- استفاده از کتابخانههای چند پردازشی برای بهرهگیری از همه هستههای CPU
- اگر از Numpy ،Pandas یا Scikit-Learn استفاده میکنید بهتر است از Rapids بهره بگیرید تا پردازش روی GPU را تسریع کند.
این راهکارها در صورتی که پردازش شما قابلیت اجرای موازی را داشته باشد، مثلاً مشغول پیشپردازش دادهها یا عملیات روی ماتریس باشید، بسیار مناسب خواهند بود. اما اگر در پایتون خالص کدنویسی میکنید و یک حلقه for بزرگ دارید که باید حتماً از آن استفاده کنید و نمیتوانید آن را در ماتریس قرار دهید و دادهها باید به صورت سری پردازش شوند، این راهکارها تفاوت چندانی ایجاد نمیکنند. این همان جایی است که سایتون (Cython) به کار میآید و میتواند سرعت اجرای کد پایتون را افزایش دهد.
Cython چیست؟
این کتابخانه در هسته مرکزی خود یک گام واسط بین پایتون و ++C/C است. این گام امکان نوشتن کد خالص پایتون با کمی اصلاحات را میدهد که در ادامه مستقیماً به کد C ترجمه میشود. تنها تغییری که باید در کد پایتون خود انجام دهید، اضافه کردن اطلاعات نوع به هر متغیر است.
به طور معمول در پایتون متغیرها را به صورت زیر اعلان میکنیم:
x = 0.5
در Cython باید نوع متغیر را نیز اضافه کنیم:
cdef float x = 0.5
بدین صورت به Cython اعلام میکنیم که متغیر ما به صورت اعشاری است و این وضعیت شبیه به کاری است که در زبان C انجام میدهیم. زمانی که کد خالص پایتون مینویسیم، نوع متغیر به صورت درجا شناسایی میشود. اعلان صریح نوع در Cython آن چیزی است که موجب میشود تبدیل کد به C ممکن شود و از این رو اعلان صریح نوع داده الزامی است. برای نصب Cython باید دستور زیر را اجرا کنید:
pip install cython
انواع در سایتون
زمانی که از Cython استفاده میکنیم، دو مجموعه متفاوت از انواع وجود دارند که یکی برای متغیرها و دیگری برای تابعها هستند. در مورد متغیرها انواع زیر را داریم:
- cdef int a, b, c
- cdef char *s
- cdef float x = 0.5 (single precision)
- cdef double x = 63.4 (double precision)
- cdef list names
- cdef dict goals_for_each_play
- cdef object card_deck
توجه کنید که همه این انواع از C/C++ ناشی میشوند. در مورد تابعها انواعی به صورت زیر داریم:
- def – تابع معمولی پایتون که صرفاً از پایتون فراخوانی میشود.
- cdef – تابعهای صرفاً Cython که نمیتواند صرفاً از پایتون مورد دسترسی قرار گیرد.
- cpdef – تابع های C و پایتون که میتواند هم از C و هم پایتون مورد دسترسی قرار گیرد.
اینک که با انواع داده در Cython آشنا شدیم، میتوانیم مستقیماً به پیادهسازی روش تسریع اجرای کد بپردازیم.
روش افزایش سرعت اجرای کد در Cython
نخستین کاری که به این منظور انجام میدهیم، راهاندازی بنچمارک کد در پایتون است. این بنچمارک شامل یک حلقه for است که برای محاسبه فاکتوریل یک عدد استفاده میشود. کد خالص پایتون به صورت زیر است:
1def test(x):
2 y = 1
3 for i in range(1, x+1):
4 y *= i
5 return y
معادل Cython کد فوق کاملاً مشابه است. ابتدا باید مطمئن شویم که فایل کد Cython دارای پسوند pyx. است. تنها تغییر در کد نیز این است که نوع هر متغیر و تابع را اعلان میکنیم:
1cpdef int test(int x):
2 cdef int y = 1
3 cdef int i
4 for i in range(1, x+1):
5 y *= i
6 return y
توجه کنید که هر تابع یک cpdef دارد تا مطمئن شویم که میتوانیم آن را از پایتون فراخوانی کنیم. ضمناً میبینید که حتی متغیر حلقه یعنی i نیز دارای نوع است. شما در Cython باید برای همه متغیرها و تابعها نوع تعیین کنید تا کامپایلر C آن نوعی که استفاده خواهد کرد را بداند. سپس یک فایل به نام setup.py ایجاد میکنیم که کد Cython را به کد C کامپایل میکند:
1from distutils.core import setup
2from Cython.Build import cythonize
3
4setup(ext_modules = cythonize('run_cython.pyx'))
در ادامه فرایند کامپایل را اجرا میکنیم:
python setup.py build_ext –inplace
اینک کد C ما کامپایل شده و آماده استفاده است. اگر به پوشهای که کد Cython قرار دارد، نگاه کنید، میبینید که همه فایلهای مورد نیاز برای اجرای C را دارید که شامل فایل run_cython.c نیز میشود. اگر در این مورد کنجکاو هستید، میتوانید نگاهی به کد C که Cython تولید کرده است بیندازید.
اکنون آماده هستیم که کد C جدید و کاملاً سریع خود را تست کنیم. کد زیر را بررسی کنید که یک تست سرعت برای مقایسه کد پایتون خام با کد Cython انجام میدهد:
1import run_python
2import run_cython
3import time
4
5number = 10
6
7start = time.time()
8run_python.test(number)
9end = time.time()
10
11py_time = end - start
12print("Python time = {}".format(py_time))
13
14start = time.time()
15run_cython.test(number)
16end = time.time()
17
18cy_time = end - start
19print("Cython time = {}".format(cy_time))
20
21print("Speedup = {}".format(py_time / cy_time))
کد فوق کاملاً سرراست است. فایلها را به روشی که در پایتون انجام میدهیم، ایمپورت کردیم و تابعها را به همان روش پایتون معمولی اجرا کردهایم. Cython روی هر نوع کد پایتون افزایش سرعت خوبی ارائه میکند و به هیچ وجهی نیاز به کار اضافی نیست. نکته کلیدی که باید توجه کنید این است که هر چه حلقههای بیشتری استفاده کنید و دادههای زیادی را مورد استفاده قرار دهید، Cython بیشتر میتواند به کمک شما بیاید.
با ملاحظه جدول زیر میبینید که Cython برای محاسبه فاکتوریل مقادیر مختلف، سرعتهای متفاوتی در اختیار ما قرار میدهد. با استفاده از Cython تا بیش از 36 برابر افزایش سرعت را شاهد هستیم.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی پایتون
- آموزش افزایش سرعت اجرای برنامهها در پایتون
- مجموعه آموزشهای برنامهنویسی
- زبان برنامه نویسی پایتون (Python) — از صفر تا صد
- آموزش پایتون (Python) — مجموعه مقالات جامع وبلاگ فرادرس
==
من اکنون از پایتون 3.11.5 در ویندوز 11 استفاده میکنم
ابزار pip بتنهایی برای نصب cython کافی نیست
سلام
ممنون از مقاله ارزشمندتون
میخواستم بدونم که سایتون رو در چه برنامههایی از پایتون میشه استفاده کرد؟ به طور مثال آیا میشه در طراحی سایت، در برنامه های سمت سرور، در برنامه های مویابل هم از سایتون برای افزایش سرعت استفاده کرد؟
ممنون میشم اگه به سوالم پاسخ بدید با تشکر.