Προγραμματισμός

Εκμάθηση Cython: Πώς να επιταχύνετε το Python

Το Python είναι μια ισχυρή γλώσσα προγραμματισμού που είναι εύκολο να μάθει και εύκολο να δουλέψει, αλλά δεν είναι πάντα η ταχύτερη εκτέλεση - ειδικά όταν ασχολείστε με μαθηματικά ή στατιστικά. Βιβλιοθήκες τρίτων όπως το NumPy, οι οποίες τυλίγουν βιβλιοθήκες C, μπορούν να βελτιώσουν σημαντικά την απόδοση ορισμένων λειτουργιών, αλλά μερικές φορές χρειάζεστε απλώς την ακατέργαστη ταχύτητα και ισχύ του C απευθείας στο Python.

Το Cython αναπτύχθηκε για να διευκολύνει τη σύνταξη επεκτάσεων C για το Python και να επιτρέψει τη μετατροπή του υπάρχοντος κώδικα Python σε C. Επιπλέον, η Cython επιτρέπει την αποστολή του βελτιστοποιημένου κώδικα με μια εφαρμογή Python χωρίς εξωτερικές εξαρτήσεις.

Σε αυτό το σεμινάριο θα ακολουθήσουμε τα βήματα που απαιτούνται για να μετατρέψουμε τον υπάρχοντα κώδικα Python σε Cython και να τον χρησιμοποιήσουμε σε μια εφαρμογή παραγωγής.

Σχετικό βίντεο: Χρήση του Cython για επιτάχυνση του Python

Ένα παράδειγμα Cython

Ας ξεκινήσουμε με ένα απλό παράδειγμα από την τεκμηρίωση της Cython, μια μη αποδοτική εφαρμογή μιας ολοκληρωμένης λειτουργίας:

def f (x):

επιστροφή x ** 2-x

def integrate_f (a, b, N):

s = 0

dx = (b-a) / Ν

για i στην περιοχή (N):

s + = f (a + i * dx)

επιστροφή s * dx

Ο κώδικας είναι ευανάγνωστος και κατανοητός, αλλά τρέχει αργά. Αυτό οφείλεται στο γεγονός ότι η Python πρέπει να μετατρέπεται συνεχώς μεταξύ των δικών της τύπων αντικειμένων και των πρώτων αριθμητικών τύπων του μηχανήματος.

Τώρα εξετάστε την έκδοση Cython του ίδιου κώδικα, με υπογραμμισμένες τις προσθήκες της Cython:

 cdef f (διπλό x):

επιστροφή 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) / Ν

για i στην περιοχή (N):

s + = f (a + i * dx)

επιστροφή s * dx

Αυτές οι προσθήκες μας επιτρέπουν να δηλώνουμε ρητά τους μεταβλητούς τύπους σε ολόκληρο τον κώδικα, έτσι ώστε ο μεταγλωττιστής Cython να μπορεί να μεταφράσει αυτές τις «διακοσμημένες» προσθήκες σε C.

Σχετικό βίντεο: Πώς ο Python διευκολύνει τον προγραμματισμό

Ιδανικό για IT, η Python απλοποιεί πολλά είδη εργασίας, από τον αυτοματισμό του συστήματος έως την εργασία σε πρωτοποριακούς τομείς όπως η μηχανική μάθηση.

Σύνταξη Cython

Οι λέξεις-κλειδιά που χρησιμοποιούνται για τη διακόσμηση του κώδικα Cython δεν βρίσκονται στη συμβατική σύνταξη Python. Αναπτύχθηκαν ειδικά για το Cython, οπότε οποιοσδήποτε κωδικός διακοσμημένος μαζί τους δεν θα λειτουργεί ως συμβατικό πρόγραμμα Python.

Αυτά είναι τα πιο κοινά στοιχεία της σύνταξης της Cython:

Μεταβλητοί τύποι

Μερικοί από τους μεταβλητούς τύπους που χρησιμοποιούνται στο Cython είναι απόηχοι των τύπων της Python, όπωςint, φλοτέρ, και μακρύς. Άλλοι τύποι μεταβλητών Cython βρίσκονται επίσης στο C, όπως απανθρακώνω ή δομ, όπως και οι δηλώσεις χωρίς υπογραφή πολύ. Και άλλοι είναι μοναδικοί για τη Cython, όπως κόρη, μια αναπαράσταση επιπέδου C της Python Σωστό Λάθος αξίες.

ο cdef και cpdef τύποι λειτουργιών

ο cdef Η λέξη-κλειδί δείχνει τη χρήση ενός τύπου Cython ή C. Χρησιμοποιείται επίσης για τον καθορισμό λειτουργιών όπως θα κάνατε στο Python.

Λειτουργίες γραμμένες στο Cython χρησιμοποιώντας Python's ορισμός η λέξη-κλειδί είναι ορατή σε άλλο κώδικα Python, αλλά επιβάλλεται ποινή απόδοσης. Λειτουργίες που χρησιμοποιούν το cdef Η λέξη-κλειδί είναι ορατή μόνο σε άλλους κωδικούς Cython ή C, αλλά εκτελείται πολύ πιο γρήγορα. Εάν έχετε λειτουργίες που καλούνται μόνο εσωτερικά από μια μονάδα Cython, χρησιμοποιήστε το cdef.

Μια τρίτη λέξη-κλειδί, cpdef, παρέχει συμβατότητα τόσο με τον κώδικα Python όσο και με τον κωδικό C, με τέτοιο τρόπο ώστε ο κώδικας C να έχει πρόσβαση στη δηλωμένη λειτουργία με πλήρη ταχύτητα. Αυτή η ευκολία κοστίζει, ωστόσο:cpdef Οι συναρτήσεις δημιουργούν περισσότερο κώδικα και έχουν ελαφρώς περισσότερες γενικές κλήσεις από cdef.

Άλλες λέξεις-κλειδιά Cython

Άλλες λέξεις-κλειδιά στο Cython παρέχουν έλεγχο σε πτυχές της ροής του προγράμματος και της συμπεριφοράς που δεν είναι διαθέσιμη στο Python:

  • gil και νογκίλ. Πρόκειται για διαχειριστές περιβάλλοντος που χρησιμοποιούνται για να οριοθετήσουν τμήματα κώδικα που απαιτούν (με gil:) ή δεν απαιτούν (με nogil:) Παγκόσμιο κλείδωμα διερμηνείας της Python ή GIL. Ο κωδικός C που δεν πραγματοποιεί κλήσεις στο Python API μπορεί να εκτελεστεί πιο γρήγορα σε ένα νογκίλ μπλοκ, ειδικά εάν εκτελεί μια μακροχρόνια λειτουργία, όπως ανάγνωση από σύνδεση δικτύου.
  • cimportΑυτό κατευθύνει τη Cython να εισάγει τύπους δεδομένων C, συναρτήσεις, μεταβλητές και τύπους επέκτασης. Οι εφαρμογές Cython που χρησιμοποιούν τις εγγενείς ενότητες C του NumPy, για παράδειγμα, χρησιμοποιούν cimport για να αποκτήσετε πρόσβαση σε αυτές τις λειτουργίες.
  • περιλαμβάνω. Αυτό τοποθετεί τον πηγαίο κώδικα ενός αρχείου Cython μέσα σε ένα άλλο, με τον ίδιο τρόπο όπως και στο C. Σημειώστε ότι το Cython έχει έναν πιο εξελιγμένο τρόπο για να μοιράζεται δηλώσεις μεταξύ αρχείων Cython εκτός από απλώς περιλαμβάνωμικρό.
  • ctypedef. Χρησιμοποιείται για αναφορά σε ορισμούς τύπων σε εξωτερικά αρχεία κεφαλίδας C.
  • εξωτερικός. Χρησιμοποιείται με cdef να αναφέρεται σε συναρτήσεις C ή μεταβλητές που βρίσκονται σε άλλες ενότητες.
  • δημόσια / api. Χρησιμοποιείται για την πραγματοποίηση δηλώσεων σε μονάδες Cython που θα είναι ορατές σε άλλο κώδικα C.
  • στη γραμμή. Χρησιμοποιείται για να δείξει μια δεδομένη συνάρτηση θα πρέπει να είναι κεκλιμένη ή να έχει τον κωδικό της τοποθετημένο στο σώμα της συνάρτησης κλήσης όποτε χρησιμοποιείται, για λόγους ταχύτητας. Για παράδειγμα, το φά λειτουργία στο παραπάνω παράδειγμα κώδικα θα μπορούσε να διακοσμηθεί με στη γραμμή για να μειώσει τη λειτουργία κλήσης γενικά, επειδή χρησιμοποιείται μόνο σε ένα μέρος. (Σημειώστε ότι ο μεταγλωττιστής C μπορεί να εκτελεί αυτόματα τη δική του κλίση, αλλά στη γραμμή σας επιτρέπει να προσδιορίσετε ρητά εάν κάτι πρέπει να είναι γραμμένο.)

Δεν είναι απαραίτητο να γνωρίζετε εκ των προτέρων όλες τις λέξεις-κλειδιά της Cython. Ο κωδικός Cython τείνει να γράφεται σταδιακά - πρώτα γράφετε έγκυρο κώδικα Python και μετά προσθέτετε διακόσμηση Cython για να την επιταχύνετε. Έτσι, μπορείτε να παραλάβετε το σύνθετο σύνθετο λέξη-κλειδί Cython, καθώς το χρειάζεστε.

Μεταγλώττιση Cython

Τώρα που έχουμε κάποια ιδέα για το πώς μοιάζει ένα απλό πρόγραμμα Cython και γιατί φαίνεται όπως φαίνεται, ας ακολουθήσουμε τα βήματα που απαιτούνται για να μεταγλωττίσουμε το Cython σε ένα δυαδικό λειτουργικό.

Για να χτίσουμε ένα λειτουργικό πρόγραμμα Cython, θα χρειαστούμε τρία πράγματα:

  1. Ο διερμηνέας Python. Χρησιμοποιήστε την πιο πρόσφατη έκδοση, εάν μπορείτε.
  2. Το πακέτο Cython. Μπορείτε να προσθέσετε το Cython στο Python μέσω του κουκούτσι διαχειριστής πακέτων: εγκατάσταση pip cython
  3. Ένας μεταγλωττιστής C.

Το στοιχείο # 3 μπορεί να είναι δύσκολο αν χρησιμοποιείτε Microsoft Windows ως πλατφόρμα ανάπτυξης. Σε αντίθεση με το Linux, τα Windows δεν συνοδεύονται από μεταγλωττιστή C ως βασικό στοιχείο. Για να το αντιμετωπίσετε, πάρτε ένα αντίγραφο του Microsoft Visual Studio Community Edition, το οποίο περιλαμβάνει τον μεταγλωττιστή C της Microsoft και δεν κοστίζει τίποτα.

Σημειώστε ότι, από αυτήν τη γραφή, η πιο πρόσφατη έκδοση του Cython είναι 0.29.16, αλλά μια έκδοση beta του Cython 3.0 είναι διαθέσιμη για χρήση. Εάν χρησιμοποιείτε εγκατάσταση pip cython, θα εγκατασταθεί η πιο πρόσφατη μη beta έκδοση. Εάν θέλετε να δοκιμάσετε το beta, χρησιμοποιήστε το εγκατάσταση pip cython> = 3.0a1 για να εγκαταστήσετε την πιο πρόσφατη έκδοση του υποκαταστήματος Cython 3.0. Οι προγραμματιστές της Cython προτείνουν να δοκιμάσετε το υποκατάστημα Cython 3.0 όποτε είναι δυνατόν, γιατί σε ορισμένες περιπτώσεις δημιουργεί πολύ πιο γρήγορο κώδικα.

Τα προγράμματα Cython χρησιμοποιούν το .κιβωτίδιο επέκταση αρχείου. Σε έναν νέο κατάλογο, δημιουργήστε ένα αρχείο με το όνομα num.pyx που περιέχει το παράδειγμα του κώδικα Cython που φαίνεται παραπάνω (το δεύτερο δείγμα κώδικα στην ενότητα "Ένα παράδειγμα Cython") και ένα αρχείο με το όνομα main.py που περιέχει τον ακόλουθο κωδικό:

από num import integrate_f

εκτύπωση (integrate_f (1.0, 10.0, 2000))

Αυτό είναι ένα κανονικό πρόγραμμα Python που θα καλέσει το ολοκλήρωση_f η συνάρτηση βρέθηκε στοnum.pyx. Ο κώδικας Python «βλέπει» τον κώδικα Cython ως μια άλλη ενότητα, οπότε δεν χρειάζεται να κάνετε κάτι άλλο εκτός από την εισαγωγή της μεταγλωττισμένης μονάδας και να εκτελέσετε τις λειτουργίες της.

Τέλος, προσθέστε ένα αρχείο με το όνομα setup.py με τον ακόλουθο κωδικό:

από distutils.core setup 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 χρησιμοποιείται συνήθως από την Python για να εγκαταστήσει τη λειτουργική μονάδα με την οποία συσχετίζεται και μπορεί επίσης να χρησιμοποιηθεί για να κατευθύνει το Python για τη μεταγλώττιση επεκτάσεων C για τη συγκεκριμένη μονάδα. Εδώ χρησιμοποιούμε setup.py για να μεταγλωττίσετε κώδικα Cython.

Εάν χρησιμοποιείτε Linux και έχετε εγκαταστήσει ένα μεταγλωττιστή C (συνήθως στην περίπτωση), μπορείτε να μεταγλωττίσετε το .κιβωτίδιο αρχείο στο C εκτελώντας την εντολή:

python setup.py build_ext --inplace

Εάν χρησιμοποιείτε Microsoft Windows και Microsoft Visual Studio 2017 ή καλύτερα, θα πρέπει να βεβαιωθείτε ότι διαθέτετε την πιο πρόσφατη έκδοση του εργαλεία εγκατάστασης εγκατεστημένο στο Python (έκδοση 46.1.3 από αυτό το γράψιμο) πριν να λειτουργήσει αυτή η εντολή. Αυτό διασφαλίζει ότι τα εργαλεία κατασκευής της Python θα μπορούν να εντοπίζουν αυτόματα και να χρησιμοποιούν την έκδοση του Visual Studio που έχετε εγκαταστήσει.

Εάν η συλλογή είναι επιτυχής, θα πρέπει να βλέπετε νέα αρχεία στον κατάλογο: αριθ. γ (το αρχείο C που δημιουργήθηκε από τη Cython) και ένα αρχείο με ένα από τα δύο .ο επέκταση (σε Linux) ή a .pyd επέκταση (στα Windows). Αυτό είναι το δυαδικό αρχείο στο οποίο έχει συνταχθεί το αρχείο C. Μπορεί επίσης να δείτε ένα \χτίζω υποκατάλογος, ο οποίος περιέχει τα αντικείμενα από τη διαδικασία κατασκευής.

Τρέξιμο python main.pyκαι θα πρέπει να δείτε κάτι σαν τα ακόλουθα να επιστρέφονται ως απάντηση:

283.297530375

Αυτή είναι η έξοδος από τη συγκεντρωμένη ολοκληρωμένη συνάρτηση, όπως επικαλέστηκε ο καθαρός κώδικας Python. Δοκιμάστε να παίξετε με τις παραμέτρους που μεταβιβάστηκαν στη συνάρτηση στο main.py για να δείτε πώς αλλάζει η έξοδος.

Σημειώστε ότι όποτε κάνετε αλλαγές στο .κιβωτίδιο αρχείο, θα πρέπει να το μεταγλωττίσετε ξανά. (Τυχόν αλλαγές που κάνετε στον συμβατικό κώδικα Python θα τεθούν σε ισχύ αμέσως.)

Το προκύπτον μεταγλωττισμένο αρχείο δεν έχει καμία εξάρτηση εκτός από την έκδοση του Python για την οποία καταρτίστηκε και έτσι μπορεί να ομαδοποιηθεί σε δυαδικό τροχό. Λάβετε υπόψη ότι εάν αναφέρεστε σε άλλες βιβλιοθήκες στον κώδικά σας, όπως το NumPy (δείτε παρακάτω), θα πρέπει να τις παρέχετε ως μέρος των απαιτήσεων της εφαρμογής.

Πώς να χρησιμοποιήσετε το Cython

Τώρα που ξέρετε πώς να "Cythonize" ένα κομμάτι κώδικα, το επόμενο βήμα είναι να προσδιορίσετε πώς η εφαρμογή Python μπορεί να επωφεληθεί από το Cython. Πού ακριβώς πρέπει να το εφαρμόσετε;

Για καλύτερα αποτελέσματα, χρησιμοποιήστε το Cython για να βελτιστοποιήσετε αυτά τα είδη λειτουργιών Python:

  1. Λειτουργίες που εκτελούνται σε στενούς βρόχους ή απαιτούν μεγάλο χρονικό διάστημα επεξεργασίας σε ένα μόνο «hot spot» κώδικα.
  2. Λειτουργίες που εκτελούν αριθμητικούς χειρισμούς.
  3. Λειτουργίες που λειτουργούν με αντικείμενα που μπορούν να αναπαρασταθούν σε καθαρό C, όπως βασικούς αριθμητικούς τύπους, πίνακες ή δομές, αντί για τύπους αντικειμένων Python όπως λίστες, λεξικά ή πλειάδες.

Η Python ήταν παραδοσιακά λιγότερο αποτελεσματική σε βρόχους και αριθμητικούς χειρισμούς από άλλες γλώσσες που δεν ερμηνεύθηκαν. Όσο περισσότερο διακοσμείτε τον κωδικό σας για να υποδείξετε ότι θα πρέπει να χρησιμοποιεί βασικούς αριθμητικούς τύπους που μπορούν να μετατραπούν σε C, τόσο πιο γρήγορα θα κάνει αριθμούς.

Η χρήση τύπων αντικειμένων Python στο Cython δεν αποτελεί από μόνη της πρόβλημα. Οι συναρτήσεις Cython που χρησιμοποιούν αντικείμενα Python θα εξακολουθούν να μεταγλωττίζονται και τα αντικείμενα Python μπορεί να είναι προτιμότερα όταν η απόδοση δεν είναι το κορυφαίο ζήτημα. Όμως, οποιοσδήποτε κώδικας που χρησιμοποιεί αντικείμενα Python θα περιορίζεται από την απόδοση του χρόνου εκτέλεσης του Python, καθώς η Cython θα δημιουργήσει κώδικα για την άμεση αντιμετώπιση των API και ABI της Python.

Ένας άλλος άξιος στόχος της βελτιστοποίησης Cython είναι ο κώδικας Python που αλληλεπιδρά άμεσα με μια βιβλιοθήκη C. Μπορείτε να παραλείψετε τον κώδικα Python "wrapper" και να επικοινωνήσετε απευθείας με τις βιβλιοθήκες.

Ωστόσο, η Cython το κάνειδεν δημιουργούν αυτόματα τις κατάλληλες διεπαφές κλήσεων για αυτές τις βιβλιοθήκες. Θα πρέπει να κάνετε το Cython να αναφέρεται στις υπογραφές της λειτουργίας στα αρχεία κεφαλίδας της βιβλιοθήκης, μέσω ενός cdef εξωτερικό από δήλωση. Σημειώστε ότι εάν δεν έχετε τα αρχεία κεφαλίδας, η Cython είναι αρκετά συγχωρητική για να σας επιτρέψει να δηλώσετε υπογραφές εξωτερικής λειτουργίας που προσεγγίζουν τις αρχικές κεφαλίδες. Αλλά χρησιμοποιήστε τα πρωτότυπα όποτε είναι δυνατόν για να είστε ασφαλείς.

Μία εξωτερική βιβλιοθήκη C που μπορεί να χρησιμοποιήσει το Cython απευθείας από το κουτί είναι το NumPy. Για να επωφεληθείτε από τη γρήγορη πρόσβαση της Cython στις συστοιχίες NumPy, χρησιμοποιήστε το cimport numpy (προαιρετικά με ως np για να διατηρήσετε το χώρο ονομάτων του ξεχωριστό) και στη συνέχεια χρησιμοποιήστε cdef δηλώσεις για δήλωση μεταβλητών NumPy, όπως cdef np.array ή np.ndarray.

Προφίλ Cython

Το πρώτο βήμα για τη βελτίωση της απόδοσης μιας εφαρμογής είναι να το σχεδιάσετε - να δημιουργήσετε μια λεπτομερή αναφορά για το πού ξοδεύεται ο χρόνος κατά την εκτέλεση. Η Python παρέχει ενσωματωμένους μηχανισμούς για τη δημιουργία προφίλ κώδικα. Η Cython όχι μόνο συνδέεται με αυτούς τους μηχανισμούς, αλλά έχει δικά της εργαλεία δημιουργίας προφίλ.

Το προφίλ του Python, cΠροφίλ, δημιουργεί αναφορές που δείχνουν ποιες συναρτήσεις καταλαμβάνουν τον περισσότερο χρόνο σε ένα δεδομένο πρόγραμμα Python. Από προεπιλογή, ο κώδικας Cython δεν εμφανίζεται σε αυτές τις αναφορές, αλλά μπορείτε να ενεργοποιήσετε τη δημιουργία προφίλ στον κώδικα Cython εισάγοντας μια οδηγία μεταγλωττιστή στην κορυφή του .κιβωτίδιο αρχείο με συναρτήσεις που θέλετε να συμπεριλάβετε στο προφίλ:

# cython: profile = True

Μπορείτε επίσης να ενεργοποιήσετε την ανίχνευση γραμμής προς γραμμή στον κώδικα C που δημιουργείται από τη Cython, αλλά αυτό επιβάλλει πολλά γενικά έξοδα και έτσι απενεργοποιείται από προεπιλογή.

Λάβετε υπόψη ότι το προφίλ επιβάλλει επιτυχία στην απόδοση, οπότε φροντίστε να απενεργοποιήσετε το προφίλ για κωδικό που αποστέλλεται στην παραγωγή.

Το Cython μπορεί επίσης να δημιουργήσει αναφορές κώδικα που υποδεικνύουν πόσο από ένα δεδομένο .κιβωτίδιο το αρχείο μετατρέπεται σε C, και πόσα παραμένει ο κώδικας Python. Για να το δείτε σε δράση, επεξεργαστείτε το setup.py αρχείο στο παράδειγμά μας και προσθέστε τις ακόλουθες δύο γραμμές στην κορυφή:

εισαγωγή Cython.Compiler.Options

Cython.Compiler.Options.annotate = True

(Εναλλακτικά, μπορείτε να χρησιμοποιήσετε μια οδηγία στο setup.py για να ενεργοποιήσετε τους σχολιασμούς, αλλά η παραπάνω μέθοδος είναι συχνά πιο εύκολη στην εργασία.)

Διαγράψτε το .ντο αρχεία που δημιουργήθηκαν στο έργο και εκτελέστε ξανά το setup.py script για να μεταγλωττίσετε τα πάντα. Όταν τελειώσετε, θα πρέπει να δείτε ένα αρχείο HTML στον ίδιο κατάλογο που μοιράζεται το όνομα του αρχείου .pyx σας - σε αυτήν την περίπτωση,num.html. Ανοίξτε το αρχείο HTML και θα δείτε τα μέρη του κώδικα που εξακολουθούν να εξαρτώνται από την Python με κίτρινη ένδειξη. Μπορείτε να κάνετε κλικ στις κίτρινες περιοχές για να δείτε τον υποκείμενο κώδικα C που δημιουργείται από τη Cython.