سایتون میانبری برای پایتون سریع!
سایتون چیست و چگونه سرعت اجرای کدهای پایتون خود را افزایش دهیم
پایتون یک زبان برنامه نویسی قدرتمند است که یادگیری و کار با آن حتی برای افراد مبتدی راحت است، اما از طرفی همیشه اجرای آن به ویژه وقتی با ریاضیات و آمار سر و کار دارید با سرعت انجام نمی‎شود. کتابخانه‎های ثالثی مثل NumPy که کتابخانه‎های C را پوشش می‎دهد می‎تواند عملکرد بعضی از عملیات‎ها را به طور قابل توجهی بهبود بخشد، اما بعضی اوقات شما مستقیما به سرعت خام و قدرت C در پایتون نیاز دارید.

سایتون (Cython) توسعه داده شده است تا امکان ساخت افزونه‎های C را برای پایتون ساده‎تر کند و به کدهای موجود پایتون اجازه دهد تا به C تبدیل شوند. علاوه بر این، سایتون این امکان را برای کدهای بهینه شده فراهم می‎کند تا بدون وابستگی‎های خارجی با پایتون همراه شوند.
در این مقاله ما مراحلی را که لازم است تا کدهای موجود پایتون به سایتون تبدیل شده و در یک اپلیکیشن کاربردی مورد استفاده قرار گیرند، بررسی خواهیم کرد.

یک مثال از سایتون 

اجازه دهید در ابتدا با یک مثال ساده که از اسناد سایتون گرفته شده کار را آغاز کنیم، یک پیاده سازی نه چندان کارآمد از یک تابع انتگرال:

def f(x):
    return x**2-x

def integrate_f(a, b, N):
    s = 0
    dx = (b-a)/N
    for i in range(N):
        s += f(a+i*dx)
    return s * dx

خواندن و درک این کد راحت است، اما اجرای آن به کندی صورت می‎گیرد. این به دلیل آن است که پایتون باید به طور دائم بین انواع شی‎های خود و انواع مقادیر عددی ماشین در رفت و آمد باشد.
حالا نسخه سایتون همین کد را در نظر بگیرید که در اینجا زیر بخش‎های اضافه شده سایتون خط کشیده شده است:

cdef f(double x):
    return x**2-x

def integrate_f(double a, double b, int N):
    cdef int i
    cdef double s, x, dx
    s = 0
    dx = (b-a)/N
    for i in range(N):
        s += f(a+i*dx)
    return s * dx

این بخش‎های اضافی به ما اجازه می‎دهد در میان این کد صریحا انواعی از متغیرها را تعریف کنیم، به این شكل کامپایلر سایتون می‎تواند این بخش‎های اضافه را به C تفسیر کند.

مطلب پیشنهادی

 آموزش کار با زبان برنامه‌نويسی پايتون (بخش دوم)

کدهای دستوری سایتون 

کلمات کلیدی که برای الصاق کدهای سایتون مورد استفاده قرار می‎گیرد، در کدهای دستوری معمول پایتون پیدا نمی‎شود. آنها منحصرا برای سایتون توسعه داده شده‎اند، بنابراین وقتی این فرامین به یک کد اضافه می‎شوند نمی‎توان آنها را به شکل یک برنامه پایتون معمولی اجرا کرد. 
اینها رایج‎ترین عناصر موجود در کدهای دستوری سایتون هستند:

نوع متغیرها 

بعضی از انواع متغیرهایی که در سایتون استفاده می‎شوند، از خود متغیرهای پایتون مثل  int, float و long اقتباس شده‎اند. سایر انواع متغیرهای سایتون نیز در C پیدا می‎شوند، مثل char یا struct، بعضی نیز به صورت unsigned long تعریف می‎شوند. باقی آنها نیز مثل bint مخصوص خود سایتون هستند.

نوع توابع cdef و cpdef

کلیدواژه cdef استفاده از نوع سایتون یا C را مشخص می‎کند. همچنین از آن برای تعریف توابعی که شما مایلید در پایتون داشته باشید، استفاده می‎شود.
توابعی که در سایتون با استفاده از کلیدواژه پایتون def نوشته می‎شوند برای سایر کدهای پایتون قابل دسترس هستند، اما با محدودیت‎های وضعیت عملکرد پایتون مواجه می‎شوند. توابعی که از کلیدواژه cdef استفاده می‎کنند تنها برای سایر کدهای سایتون و C قابل دسترس هستند، اما خیلی سریع‎تر اجرا می‎شوند. اگر شما توابعی دارید که تنها به صورت داخلی در خود ماژول سایتون فراخوانی می‎شوند، از cdef استفاده کنید.
سومین کلیدواژه cpdef است که امکان سازگاری با کدهای پایتون و کدهای C را به شیوه‎ای که کدهای C می‎توانند با حداکثر سرعت به این تابع دسترسی داشته باشد فراهم می‎کند. هر چند این سهولت در کار پیامدهایی را نیز در پی دارد: توابع cpdef کدهای بیشتری تولید می‎کنند و نسبت به cdef فراخوانی آنها منابع بیشتری نیاز دارد.
سایر کلیدواژه‎های سایتون سایر کلمات کلیدی در سایتون کنترل جنبه‎های مختلف چرخه برنامه را که در پایتون وجود ندارد، برعهده دارند:

• Gil و nogil مدیریت منابعی را برعهده دارند که برای معین کردن بخش‎هایی از کد که به Global Interpreter Lock پایتون نیاز دارد (با gil:) یا نیاز ندارد (با nogil:) استفاده می‎شود. کدهای C که هیچ فراخوانی به API پایتون ندارند، در یک بلوک nogil سریع‌تر اجرا می‎شوند، به ویژه اگر یک عملیات طولانی را اجرا کنند.
• از cimport برای نظارت بر ورود نوع داده، تابع، متغیرها و نوع افزونه  C به سایتون استفاده می‎شود. برای نمونه، اپلیکیشن‎های سایتون که از ماژول NumPy اصلی C استفاده می‎کنند، از cimport برای فراهم کردن امکان دسترسی به این توابع استفاده می‎کنند.
• Include کد منبع یک فایل سایتون را به همان شیوه موجود در C به کدهای دیگر اضافه می‎کند. توجه داشته باشید كه سایتون از یک روش پیچیده‎تری برای اشتراک گذاشتن عبارات بین فایل‎های سایتون نسبت به include استفاده می‎کند.
• از ctypedef برای ارجاع به هدر فایل‎های خارجی C استفاده می‎شود.
• از Extern با cdef استفاده می‎شود تا به توابع C یا متغیرهای پیدا شده در سایر ماژول‎ها مراجعه کند.
• از public/api استفاده می‎شود تا عباراتی را در ماژول‎های سایتون ایجاد کند که می‎توان در سایر کدهای C به آن دسترسی داشت. 
•  از inline استفاده می‎شود تا یک تابع را به صورت خطی تعریف کرد، و یا کدهای آن را به منظور افزایش سرعت در بدنه تابع فراخوانی شده به کار گرفت. برای نمونه تابع f در کد مثال بالا می‎تواند به inline مجهز شود تا سرعت فراخوانی را افزایش دهد، زیرا از آن تنها در یک مکان استفاده می‎شود.
نیازی نیست که پیشاپیش از تمام کلمات کلیدی سایتون آگاه باشید. کدهای سایتون به شکلی در نظر گرفته شده‎اند که می‎توان آنها را به تدریج نوشت. ابتدا شما کد پایتون را می‎نویسید، سپس ضمایم سایتون را به منظور افزایش سرعت به آن اضافه می‎کنید. به این شكل شما می‎توانید به تدریج کلیدواژه فرامین دستوری سایتون را برداشته و بر اساس نیاز خود استفاده کنید.

کامپایل سایتون 

حالا که با نحوه عملکرد یک برنامه ساده سایتون آشنا شدید، در ادامه قصد داریم مراحل مورد نیاز را برای کامپایل سایتون به یک فایل باینری قابل اجرا بررسی کنیم.
برای ساخت یک برنامه قابل اجرای سایتون ما به سه چیز نیاز خواهیم داشت:

1. مفسر پایتون، در صورت امکان از آخرین نسخه منتشر شده استفاده کنید.
2. بسته سایتون، شما می‎توانید با استفاده از روش مدیر پکیج pip به صورت pip install cython سایتون را به پایتون اضافه کنید.
3. یک کامپایلر C 

اگر شما از ویندوز مایکروسافت به عنوان پلتفرم توسعه خود استفاده می‎کنید باید گزینه شماره 3 را مد نظر داشته باشید. برخلاف لینوکس، ویندوز به عنوان یک تجهیزات استاندارد به کامپایلر C مجهز نیست. برای دستیابی به این ویژگی یک کپی از Microsoft Visual Studio Community Edition انتخاب کنید که با کامپایلر C مایکروسافت همراه است و هزینه‎ای برای شما به همراه ندارد.
برنامه‎های سایتون از پسوند فایل .pyx استفاده می‎کنند. در یک دایرکتوری جدید یک فایل به نام num.pyx ایجاد کنید که شامل کد سایتون نمایش داده شده در مثال بالا است و یک فایل دیگر به نام
main.py بسازید که شامل کد زیر است:

from num import integrate_f
print (integrate_f(1.0, 10.0, 2000))

این یک برنامه عادی پایتون است که تابع integrate_f  موجود در num.pyx را فراخوانی می‎کند. کد پایتون با کد سایتون تنها به شکل یک ماژول دیگر برخورد می‎کند، بنابراین شما به جز وارد کردن این ماژول کامپایل شده و اجرای توابع آن نیاز نیست کار خاص دیگری انجام دهید.
سرانجام، یک فایل دیگر با نام setup.py با کد زیر اضافه کنید:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

ext_modules = [
    Extension(
        r’num’,
        [r’num.pyx’]
    ),
]

setup(
    name=’num’,
    ext_modules=cythonize(ext_modules),
)

setup.py در حالت عادی توسط پایتون برای نصب ماژول همراه با آن استفاده می‎شود و همچنین می‎توان از آن برای کامپایل مستقیم افزونه‎های C در پایتون استفاده کرد. در اینجا ما از setup.py برای کامپایل کدهای سایتون استفاده می‎کنیم.
اگر شما از لینوکس استفاده می‎کنید و یک کامپایلر C نصب شده دارید می‎توانید فایل .pyx را با اجرای این فرمان به C کامپایل کنید:

> python setup.py build_ext --inplace

اگر از ویندوز استفاده می‎کنید باید یک فایل بچ به نام compile.bat اضافه کنید تا فرآيند کامپایل را خودکارسازی کند:

@SETLOCAL
set DISTUTILS_USE_SDK=1
call “C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat” amd64
python setup.py build_ext --inplace --compiler=msvc

توجه داشته باشید كه مسیر درست به vcvarsall.bat در خط 3 به نسخه ویژوال استودیو که شما نصب کرده‎اید، بستگی دارد. فرض این مثال بر این است که شما از Visual Studio 2017 Community استفاده کرده‎اید.
اگر عمل کامپایل با موفقیت انجام شود، شما باید فایل‎های جدیدی را در این دایرکتوری مشاهده کنید: num.c (فایل C تولید شده توسط سایتون) و یک فایل با پسوند .o (در لینوکس ) یا .pyd (در ویندوز). این همان فایل باینری است که فایل C به آن کامپایل شده است. شما ممکن است یک دایرکتوری به نام \build را نیز مشاهده کنید که شامل مصنوعاتی از فرآیند ساخت است.
فرمان python main.py را اجرا کنید تا به عنوان پاسخ برگشتی چیزی شبیه به این را مشاهده کنید:

283.297530375

این همان خروجی تابع انتگرال کامپایل شده که توسط کد اصلی پایتون ما فراخوانی شده است. با پارامترهای این تابع در main.py بازی کنید تا ببینید این خروجی چگونه تغییر می‎کند.
توجه داشته باشید هر زمان که شما تغییراتی را به فایل .pyx اعمال می‎کنید باید آن را دوباره کامپایل کنید. مسلما هر تغییری که شما روی کدهای معمول پایتون اعمال کنید فورا تاثیرگذار خواهد بود.
نتیجه فایل کامپایل شده هیچ وابستگی بجز نسخه پایتونی که برای آن کامپایل شده ندارد و به همین دلیل می‎توان آن را به یک binary wheel الصاق کرد. توجه داشته باشید كه اگر شما در کد خود به سایر کتابخانه‎ها مثل NumPy  (در ادامه به آن خواهیم پرداخت) ارجاع داشته باشید باید آنها را به عنوان بخشی از عناصر مورد نیاز اپلیکیشن خود فراهم کنید.

مطلب پیشنهادی

10 زبان برنامه‌نویسی محبوب و تأثیرگذار سال

چگونه از سایتون استفاده کنیم 

حالا که متوجه شدیم چگونه می‎توان یک کد را به سایتون تبدیل کرد، مرحله بعدی این است که ببینیم چگونه اپلیکیشن پایتون شما می‎تواند از مزایای سایتون استفاده کند. و دقیقا کجا باید آن را به کار بگیرید؟
برای دریافت نتیجه بهتر، از سایتون برای بهینه سازی این نوع از توابع پایتون استفاده کنید:
• توابعی که در چرخه‎های فشرده اجرا می‎شوند یا در یک بخش مهم و حیاتی از یک کد نیاز به مقدار زیادی زمان پردازش دارند.
• توابعی که به انجام اعمال عددی می‎پردازند.
• توابعی که با شی‎هایی کار می‎کنند که در زبان C وجود دارند. مثل انواع عددی، آرایه‎ها یا ساختارها به جای انواع شی‎های پایتون مثل لیست‎ها، دیکشنری‎ها یا تاپل‎ها.
پایتون نسبت به سایر زبان‎های غیر تفسیری اصولا در چرخه‎ها و انجام اعمال عددی کارایی پایین‎تری دارد. هر چه شما بیشتر از انواع عددی تبدیل شده به C در کد خود استفاده کنید، محاسبات عددی سریع‎تر انجام خواهد شد.
استفاده از انواع شی‎های پایتون در سایتون به خودی خود مشکل‌ساز نیست. توابع سایتون که از شی‎های پایتون استفاده می‎کنند همچنان کامپایل می‎شوند و زمانی که عملکرد اولويت اصلی نیست شی‎های پایتون ترجيح داده می‎شوند. اما هر کدی که از شی‎های پایتون استفاده می‎کند با مشکلات عملکرد ذاتی پایتون مواجه می‎شود زیرا سایتون کدها را مستقیم بر اساس API و ABIهای پایتون تولید خواهد کرد.
یکی دیگر از اهداف ارزشمند بهینه‌سازی با سایتون کدهای پایتونی است که مستقیم با یک کتابخانه C در تعامل است. شما می‎توانید از کد wrapper پایتون صرف نظر کرده و مستقیم با کتابخانه‎ها در ارتباط باشید.
اما سایتون نمی‎تواند به طور خودکار فراخوانی مناسب را برای ارتباط با این کتابخانه‎ها توليد کند. شما باید سایتون را به شکلی تنظیم کنید که در هدر فایل‎های کتابخانه‎ها به توابع ارجاع داده شود. روش انجام این کار استفاده از دستور cdef extern from است.
یکی از کتابخانه‎های خارجی C که سایتون می‎تواند مستقیم از آن استفاده کند NumPy است. برای بهره‌مند شدن از دسترسی سريع سایتون به آرایه‎های NumPy از cimport numpy استفاده کنید و سپس از دستورالعمل‎های cdef برای مشخص کردن متغیرهای NumPy از قبیل cdef np.array یا np.ndarray استفاده کنید.

نمایه‌سازی سایتون 

اولین مرحله برای ارتقای عملکرد یک اپلیکیشن نمایه (profile) کردن آن برای تولید یک گزارش دقیق از جایی است که زمان در طی اجرای اپلیکیشن صرف می‎شود. برای این کار پایتون یکسری مکانیزم‎های داخلی را برای توليد کد نمایه‎ها ارائه می‎کند. سایتون نه تنها می‎تواند از این مکانیزم‎ها استفاده کند، بلکه ابزار نمایه سازی اختصاصی خود را نیز دارد. cProfile نمایه ساز خود پایتون است که گزارش‌‌‌هایی را از بیشترین زمان مصرفی توسط توابع را در یک برنامه پایتون توليد می‎کند. 
در حالت پیش فرض کدهای سایتون در این گزارش‌‌ها نمایش داده نمی‎شوند اما شما می‎توانید با وارد کردن یک دستورالعمل کامپایلر در بالای فایل .pyx به همراه توابعی که می‎خواهید در نمایه‌سازی شما حضور داشته باشد نمایه‌سازی کدهای سایتون را فعال کنید :

# cython: profile=True

سایتون همچنین می‎تواند گزارش‌‌هایی مبنی بر میزان تبدیل شدن فایل .pyx به C و میزان کدهای باقی مانده پایتون را نیز تولید کند. برای انجام این کار فایل setup.py مثال خود را باز می‎کنیم و دو خط زیر را به بالای آن اضافه می‎کنیم:

import Cython.Compiler.Options
Cython.Compiler.Options.annotate = True

حالا فایل‎های .c تولید شده در این پروژه را پاک کنید و برای کامپایل دوباره همه چیز اسکریپت  setup.py را دوباره اجرا کنید. بعد از انجام این کار شما یک فایل HTML (در مثال ما num.html) را در همان دایرکتوری که فایل .pyx قرار دارد، مشاهده خواهید کرد. فایل HTML را باز کنید تا بخش‎هایی از کد خود را که همچنان به پایتون وابسته است با هایلایت زرد رنگ مشاهده کنید. با کلیک روی نواحی زرد رنگ کدهای C تولید شده توسط سایتون را مشاهده خواهید کرد. (شکل یک)

سایتون چیست و چگونه سرعت اجرای کدهای پایتون خود را افزایش دهیم

در این مورد تابع cdef f با وجود داشتن یک تابع cdef و متغیر آن که به وضوح تایپ شده، همچنان با رنگ زرد هایلایت شده است. این به دلیل آن است که مقدار بازگشتی این تابع تایپ نشده است. سایتون فرض را بر این می‎گذارد که این تابع به جای یک double، یک شی پایتون را بازمی‎گرداند، به همین دلیل کد API پایتون را برای اداره آن تولید می‎کند.

برچسب: