Πώς να βελτιστοποιήσετε τα σενάρια Python για καλύτερη απόδοση

Pos Na Beltistopoiesete Ta Senaria Python Gia Kalytere Apodose



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

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

  1. Ενισχύστε την απόδοση της εφαρμογής
  2. Δημιουργήστε ευανάγνωστο και οργανωμένο κώδικα
  3. Απλοποιήστε την παρακολούθηση και τον εντοπισμό σφαλμάτων
  4. Εξοικονόμηση σημαντικής υπολογιστικής ισχύος και ούτω καθεξής

Προφίλ του κωδικού σας

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







Απόσπασμα κώδικα:



εισαγωγή cΠροφίλ όπως και cP
def υπολογισμός Άθροισμα ( Αριθμός εισαγωγής ) :
άθροισμα_των_εισαγωγών_αριθμών = 0
ενώ Αριθμός εισαγωγής > 0 :
sum_of_input_numbers + = inputNumber % 10
inputNumber // = 10
Τυπώνω ( 'Το άθροισμα όλων των ψηφίων στον αριθμό εισαγωγής είναι: 'sum_of_input_numbers'' )
ΕΠΙΣΤΡΟΦΗ άθροισμα_των_εισαγωγών_αριθμών
def main_func ( ) :
cP. τρέξιμο ( 'calculateSum(9876543789)' )
αν __όνομα__ == '__κύριος__' :
main_func ( )

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



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





Επιλέξτε τη σωστή δομή δεδομένων

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



Αξιολογούμε τον χρόνο που χρειάζεται για να ελέγξουμε εάν ένα στοιχείο υπάρχει σε κάθε δομή δεδομένων—μια λίστα, ένα σύνολο και ένα λεξικό—και τα συγκρίνουμε.

OptimizeDataType.py:

εισαγωγή Timei όπως και tt
εισαγωγή τυχαίος όπως και rndobj
# Δημιουργήστε μια λίστα ακεραίων
τυχαία_λίστα_δεδομένων = [ rndobj. randint ( 1 , 10000 ) Για _ σε εύρος ( 10000 ) ]
# Δημιουργήστε ένα σύνολο από τα ίδια δεδομένα
τυχαία_δεδομένα_σύνολο = σειρά ( τυχαία_λίστα_δεδομένων )

# Δημιουργήστε ένα λεξικό με τα ίδια δεδομένα με τα κλειδιά
obj_DataDictionary = { σε ένα: Κανένας Για σε ένα σε τυχαία_λίστα_δεδομένων }

# Στοιχείο προς αναζήτηση (υπάρχει στα δεδομένα)
τυχαίος_αριθμός_για_εύρεση = rndobj. επιλογή ( τυχαία_λίστα_δεδομένων )

# Μετρήστε το χρόνο για να ελέγξετε τη συμμετοχή σε μια λίστα
list_time = tt. Timei ( λάμδα : random_number_to_find σε τυχαία_λίστα_δεδομένων , αριθμός = 1000 )

# Μετρήστε το χρόνο για να ελέγξετε τη συμμετοχή σε ένα σετ
καθορισμός_χρόνου = tt. Timei ( λάμδα : random_number_to_find σε τυχαία_δεδομένα_σύνολο , αριθμός = 1000 )

# Μετρήστε το χρόνο για να ελέγξετε τη συμμετοχή σε ένα λεξικό
dict_time = tt. Timei ( λάμδα : random_number_to_find σε obj_DataDictionary , αριθμός = 1000 )

Τυπώνω ( φά 'Χρόνος ελέγχου ιδιότητας μέλους λίστας: {list_time:.6f} δευτερόλεπτα' )
Τυπώνω ( φά 'Ορισμός χρόνου ελέγχου συνδρομής: {set_time:.6f} δευτερόλεπτα' )
Τυπώνω ( φά 'Χρόνος ελέγχου ιδιότητας μέλους λεξικού: {dict_time:.6f} δευτερόλεπτα' )

Αυτός ο κωδικός συγκρίνει την απόδοση λιστών, συνόλων και λεξικών κατά την εκτέλεση ελέγχων μέλους. Γενικά, τα σύνολα και τα λεξικά είναι σημαντικά ταχύτερα από τις λίστες για δοκιμές συμμετοχής επειδή χρησιμοποιούν αναζητήσεις που βασίζονται σε κατακερματισμό, επομένως έχουν μέση χρονική πολυπλοκότητα O(1). Οι λίστες, από την άλλη πλευρά, πρέπει να κάνουν γραμμικές αναζητήσεις που καταλήγουν σε τεστ ιδιότητας μέλους με πολυπλοκότητα χρόνου O(n).

  Ένα στιγμιότυπο οθόνης ενός υπολογιστή Περιγραφή δημιουργήθηκε αυτόματα

Χρησιμοποιήστε τις ενσωματωμένες συναρτήσεις αντί για βρόχους

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

Ας δημιουργήσουμε κάποιο δείγμα κώδικα για να συγκρίνουμε την απόδοση της δημιουργίας προσαρμοσμένων βρόχων χρησιμοποιώντας τις ενσωματωμένες συναρτήσεις για τυπικές εργασίες (όπως map(), filter() και sorted()). Θα αξιολογήσουμε πόσο καλά αποδίδουν οι διάφορες μέθοδοι χαρτογράφησης, φιλτραρίσματος και ταξινόμησης.

BuiltInFunctions.py:

εισαγωγή Timei όπως και tt
# Δείγμα λίστας αριθμών_λίστας
αριθμοί_λίστα = λίστα ( εύρος ( 1 , 10000 ) )

# Συνάρτηση σε τετραγωνισμό αριθμών_λίστας χρησιμοποιώντας βρόχο
def Square_using_loop ( αριθμοί_λίστα ) :
τετράγωνο_αποτέλεσμα = [ ]
Για σε ένα σε αριθμοί_λίστα:
τετράγωνο_αποτέλεσμα. προσαρτώ ( σε ένα ** 2 )
ΕΠΙΣΤΡΟΦΗ τετράγωνο_αποτέλεσμα
# Λειτουργία για φιλτράρισμα ζυγών αριθμών_λίστας χρησιμοποιώντας βρόχο
def filter_even_using_loop ( αριθμοί_λίστα ) :
φίλτρο_αποτελέσματος = [ ]
Για σε ένα σε αριθμοί_λίστα:
αν σε ένα % 2 == 0 :
φίλτρο_αποτελέσματος. προσαρτώ ( σε ένα )
ΕΠΙΣΤΡΟΦΗ φίλτρο_αποτελέσματος
# Λειτουργία ταξινόμησης αριθμών_λίστας χρησιμοποιώντας βρόχο
def sort_using_loop ( αριθμοί_λίστα ) :
ΕΠΙΣΤΡΟΦΗ ταξινομημένο ( αριθμοί_λίστα )
# Μετρήστε το χρόνο για να τετραγωνιστεί η λίστα αριθμών_ χρησιμοποιώντας το map()
map_time = tt. Timei ( λάμδα : λίστα ( χάρτης ( λάμδα x: x ** 2 , αριθμοί_λίστα ) ) , αριθμός = 1000 )
# Μετρήστε το χρόνο για να φιλτράρετε τη λίστα ζυγών αριθμών χρησιμοποιώντας το filter()
χρόνος_φίλτρου = tt. Timei ( λάμδα : λίστα ( φίλτρο ( λάμδα x: x % 2 == 0 , αριθμοί_λίστα ) ) , αριθμός = 1000 )
# Μετρήστε το χρόνο ταξινόμησης αριθμών_list χρησιμοποιώντας sorted()
sorted_time = tt. Timei ( λάμδα : ταξινομημένο ( αριθμοί_λίστα ) , αριθμός = 1000 )
# Μετρήστε τον χρόνο για να τετραγωνιστεί η λίστα αριθμών_ χρησιμοποιώντας έναν βρόχο
loop_map_time = tt. Timei ( λάμδα : Square_using_loop ( αριθμοί_λίστα ) , αριθμός = 1000 )
# Μετρήστε το χρόνο φιλτραρίσματος της λίστας ζυγών αριθμών χρησιμοποιώντας έναν βρόχο
loop_filter_time = tt. Timei ( λάμδα : filter_even_using_loop ( αριθμοί_λίστα ) , αριθμός = 1000 )
# Μετρήστε το χρόνο για να ταξινομήσετε τη λίστα αριθμών χρησιμοποιώντας έναν βρόχο
loop_sorted_time = tt. Timei ( λάμδα : sort_using_loop ( αριθμοί_λίστα ) , αριθμός = 1000 )
Τυπώνω ( 'Η λίστα αριθμών περιέχει 10000 στοιχεία' )
Τυπώνω ( φά 'Χάρτης() Χρόνος: {map_time:.6f} δευτερόλεπτα' )
Τυπώνω ( φά 'Filter() Time: {filter_time:.6f} seconds' )
Τυπώνω ( φά 'Sorted() Time: {sorted_time:.6f} seconds' )
Τυπώνω ( φά 'Χρόνος βρόχου (Χάρτης): {loop_map_time:.6f} δευτερόλεπτα' )
Τυπώνω ( φά 'Χρόνος βρόχου (φίλτρου): {loop_filter_time:.6f} δευτερόλεπτα' )
Τυπώνω ( φά 'Χρόνος βρόχου (ταξινόμησης): {loop_sorted_time:.6f} δευτερόλεπτα' )

Πιθανότατα θα παρατηρήσουμε ότι οι ενσωματωμένες συναρτήσεις (map(), filter() και sorted()) είναι πιο γρήγορες από τους προσαρμοσμένους βρόχους για αυτές τις κοινές εργασίες. Οι ενσωματωμένες λειτουργίες στην Python προσφέρουν μια πιο συνοπτική και κατανοητή προσέγγιση για την εκτέλεση αυτών των εργασιών και είναι εξαιρετικά βελτιστοποιημένες για απόδοση.

Βελτιστοποιήστε τους βρόχους

Εάν η εγγραφή των βρόχων είναι απαραίτητη, υπάρχουν μερικές τεχνικές που μπορούμε να κάνουμε για να τους επιταχύνουμε. Γενικά, ο βρόχος range() είναι πιο γρήγορος από την επανάληψη προς τα πίσω. Αυτό συμβαίνει επειδή το range() δημιουργεί έναν επαναλήπτη χωρίς να αντιστρέφει τη λίστα, κάτι που μπορεί να είναι μια δαπανηρή λειτουργία για μεγάλες λίστες. Επιπλέον, δεδομένου ότι το range() δεν δημιουργεί μια νέα λίστα στη μνήμη, χρησιμοποιεί λιγότερη μνήμη.

OptimizeLoop.py:

εισαγωγή Timei όπως και tt
# Δείγμα λίστας αριθμών_λίστας
αριθμοί_λίστα = λίστα ( εύρος ( 1 , 100000 ) )
# Λειτουργία για επανάληψη στη λίστα με αντίστροφη σειρά
def loop_reverse_itation ( ) :
αποτέλεσμα_αντίστροφο = [ ]
Για ι σε εύρος ( μόνο ( αριθμοί_λίστα ) - 1 , - 1 , - 1 ) :
αποτέλεσμα_αντίστροφο. προσαρτώ ( αριθμοί_λίστα [ ι ] )
ΕΠΙΣΤΡΟΦΗ αποτέλεσμα_αντίστροφο
# Λειτουργία για επανάληψη στη λίστα χρησιμοποιώντας το range()
def επανάληψη_εύρος_βρόχου ( ) :
εύρος_ αποτελεσμάτων = [ ]
Για κ σε εύρος ( μόνο ( αριθμοί_λίστα ) ) :
εύρος_ αποτελεσμάτων. προσαρτώ ( αριθμοί_λίστα [ κ ] )
ΕΠΙΣΤΡΟΦΗ εύρος_ αποτελεσμάτων
# Μετρήστε το χρόνο που απαιτείται για την εκτέλεση της αντίστροφης επανάληψης
αντίστροφη_χρόνος = tt. Timei ( loop_reverse_itation , αριθμός = 1000 )
# Μετρήστε το χρόνο που χρειάζεται για να εκτελέσετε επανάληψη εύρους
εύρος_χρόνος = tt. Timei ( επανάληψη_εύρος_βρόχου , αριθμός = 1000 )
Τυπώνω ( 'Η λίστα αριθμών περιέχει 100.000 εγγραφές' )
Τυπώνω ( φά 'Reverse Iteration Time: {reverse_time:.6f} seconds' )
Τυπώνω ( φά 'Χρόνος επανάληψης εύρους: {range_time:.6f} δευτερόλεπτα' )

Αποφύγετε τις περιττές κλήσεις λειτουργιών

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

Εργαλεία προφίλ

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

Αποτελέσματα προσωρινής μνήμης

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

Ανακατασκευή κώδικα

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

Χρησιμοποιήστε τη συλλογή Just-in-Time (JIT)

Βιβλιοθήκες όπως η PyPy ή η Numba μπορούν να παρέχουν μια συλλογή JIT που μπορεί να επιταχύνει σημαντικά ορισμένους τύπους κώδικα Python.

Αναβάθμιση Python

Βεβαιωθείτε ότι χρησιμοποιείτε την πιο πρόσφατη έκδοση της Python, καθώς οι νεότερες εκδόσεις συχνά περιλαμβάνουν βελτιώσεις απόδοσης.

Παραλληλισμός και Συγχρονισμός

Για διεργασίες που μπορούν να παραλληλιστούν, διερευνήστε τις τεχνικές παράλληλης και συγχρονισμού, όπως η πολυεπεξεργασία, το threading ή το asyncio.

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

συμπέρασμα

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