Cách tối ưu hóa tập lệnh Python của bạn để có hiệu suất tốt hơn

Cach Toi Uu Hoa Tap Lenh Python Cua Ban De Co Hieu Suat Tot Hon



Tối ưu hóa các tập lệnh Python để có hiệu suất tốt hơn bao gồm việc xác định và giải quyết các điểm nghẽn trong mã của chúng ta, giúp mã chạy nhanh hơn và hiệu quả hơn. Python là ngôn ngữ lập trình phổ biến và mạnh mẽ, được sử dụng trong nhiều ứng dụng hiện nay bao gồm phân tích dữ liệu, dự án ML (học máy), phát triển web, v.v. Tối ưu hóa mã Python là một chiến lược nhằm cải thiện tốc độ và hiệu quả của chương trình dành cho nhà phát triển khi thực hiện bất kỳ hoạt động nào sử dụng ít dòng mã hơn, ít bộ nhớ hơn hoặc tài nguyên bổ sung. Mã lớn và không hiệu quả có thể làm chậm chương trình, dẫn đến mức độ hài lòng của khách hàng kém và tổn thất tài chính tiềm ẩn hoặc cần phải thực hiện nhiều công việc hơn để khắc phục và khắc phục sự cố.

Điều này là cần thiết khi thực hiện một tác vụ yêu cầu xử lý một số hành động hoặc dữ liệu. Do đó, việc loại bỏ và tăng cường một số khối mã và chức năng không hiệu quả có thể mang lại những kết quả đáng kinh ngạc như sau:

  1. Tăng hiệu suất của ứng dụng
  2. Tạo mã dễ đọc và có tổ chức
  3. Làm cho việc giám sát và gỡ lỗi lỗi trở nên đơn giản hơn
  4. Bảo tồn sức mạnh tính toán đáng kể, v.v.

Hồ sơ mã của bạn

Trước khi bắt đầu tối ưu hóa, điều cần thiết là xác định các phần của mã dự án đang làm chậm nó. Các kỹ thuật lập hồ sơ bằng Python bao gồm các gói cProfile và profile. Sử dụng các công cụ như vậy để đánh giá tốc độ thực thi các chức năng và dòng mã nhất định. Mô-đun cProfile tạo ra một báo cáo nêu chi tiết thời gian chạy của mỗi hàm tập lệnh. Báo cáo này có thể giúp chúng tôi tìm ra bất kỳ chức năng nào đang chạy chậm để chúng tôi có thể cải thiện chúng.







Đoạn mã:



nhập khẩu hồ sơ c BẰNG CP
chắc chắn tính tổng ( số đầu vào ) :
tổng_of_input_numbers = 0
trong khi số đầu vào > 0 :
tổng_of_input_numbers + = số đầu vào % 10
số đầu vào // = 10
in ( 'Tổng của tất cả các chữ số trong số đầu vào là: 'sum_of_input_numbers'' )
trở lại tổng_of_input_numbers
chắc chắn main_func ( ) :
cP. chạy ( 'tínhSum(9876543789)' )
nếu như __tên__ == '__chủ yếu__' :
main_func ( )

Chương trình thực hiện tổng cộng năm lệnh gọi hàm như được thấy ở dòng đầu tiên của đầu ra. Chi tiết về từng lệnh gọi hàm được hiển thị trong một số dòng sau, bao gồm số lần hàm được gọi, tổng thời lượng trong hàm, khoảng thời gian cho mỗi lệnh gọi và tổng thời gian trong hàm (bao gồm cả tất cả các hàm mà nó được gọi).



Ngoài ra, chương trình còn in một báo cáo trên màn hình nhắc cho thấy chương trình hoàn thành thời gian thực hiện tất cả các tác vụ của nó trong vòng 0,000 giây. Điều này cho thấy tốc độ của chương trình.





Chọn cấu trúc dữ liệu phù hợp

Đặc tính hiệu suất phụ thuộc vào cấu trúc dữ liệu. Đặc biệt, từ điển tra cứu nhanh hơn các danh sách liên quan đến việc lưu trữ cho mục đích chung. Chọn cấu trúc dữ liệu phù hợp nhất cho các hoạt động mà chúng tôi sẽ tiến hành trên dữ liệu của bạn nếu bạn biết những điều đó. Ví dụ sau đây điều tra tính hiệu quả của các cấu trúc dữ liệu khác nhau cho một quy trình giống hệt nhau để xác định xem một phần tử trong cấu trúc dữ liệu có hiện diện hay không.



Chúng tôi đánh giá thời gian cần thiết để kiểm tra xem một phần tử có xuất hiện trong mỗi cấu trúc dữ liệu hay không—danh sách, tập hợp và từ điển—và so sánh chúng.

OptimizeDataType.py:

nhập khẩu Hiện tôi BẰNG tt
nhập khẩu ngẫu nhiên BẰNG rnobj
# Tạo danh sách các số nguyên
danh sách dữ liệu ngẫu nhiên = [ rnobj. randint ( 1 , 10000 ) _ TRONG phạm vi ( 10000 ) ]
# Tạo một tập hợp từ cùng một dữ liệu
tập dữ liệu ngẫu nhiên = bộ ( danh sách dữ liệu ngẫu nhiên )

# Tạo một từ điển có cùng dữ liệu với khóa
obj_DataDictionary = { trên một: Không có trên một TRONG danh sách dữ liệu ngẫu nhiên }

# Phần tử cần tìm kiếm (tồn tại trong dữ liệu)
ngẫu nhiên_số_để_tìm = rnobj. sự lựa chọn ( danh sách dữ liệu ngẫu nhiên )

# Đo thời gian kiểm tra tư cách thành viên trong danh sách
danh sách_thời gian = tt. Hiện tôi ( lambda : số_ngẫu nhiên_để_tìm TRONG danh sách dữ liệu ngẫu nhiên , con số = 1000 )

# Đo thời gian kiểm tra tư cách thành viên trong một tập hợp
cài đặt thời gian = tt. Hiện tôi ( lambda : số_ngẫu nhiên_để_tìm TRONG tập dữ liệu ngẫu nhiên , con số = 1000 )

# Đo thời gian kiểm tra tư cách thành viên trong từ điển
dict_time = tt. Hiện tôi ( lambda : số_ngẫu nhiên_để_tìm TRONG obj_DataDictionary , con số = 1000 )

in ( f 'Thời gian kiểm tra tư cách thành viên của danh sách: {list_time:.6f} giây' )
in ( f 'Đặt thời gian kiểm tra tư cách thành viên: {set_time:.6f} giây' )
in ( f 'Thời gian kiểm tra tư cách thành viên từ điển: {dict_time:.6f} giây' )

Mã này so sánh hiệu suất của danh sách, bộ và từ điển khi thực hiện kiểm tra tư cách thành viên. Nhìn chung, các bộ và từ điển nhanh hơn đáng kể so với các danh sách dành cho kiểm tra tư cách thành viên vì chúng sử dụng tra cứu dựa trên hàm băm, do đó chúng có độ phức tạp về thời gian trung bình là O(1). Mặt khác, các danh sách phải thực hiện tìm kiếm tuyến tính dẫn đến các bài kiểm tra tư cách thành viên với độ phức tạp về thời gian O(n).

  Ảnh chụp màn hình máy tính Mô tả được tạo tự động

Sử dụng các hàm tích hợp thay vì vòng lặp

Nhiều hàm hoặc phương thức tích hợp sẵn trong Python có thể được sử dụng để thực hiện các tác vụ điển hình như lọc, sắp xếp và ánh xạ. Việc sử dụng các quy trình này thay vì tạo vòng lặp sẽ giúp tăng tốc mã vì chúng thường được tối ưu hóa hiệu suất.

Hãy xây dựng một số mã mẫu để so sánh hiệu suất của việc tạo vòng lặp tùy chỉnh bằng cách sử dụng các hàm dựng sẵn cho các công việc thông thường (chẳng hạn như map(), filter() vàsort()). Chúng tôi sẽ đánh giá các phương pháp ánh xạ, lọc và sắp xếp khác nhau hoạt động tốt như thế nào.

BuiltInFunctions.py:

nhập khẩu Hiện tôi BẰNG tt
# Danh sách mẫu_list
danh sách số = danh sách ( phạm vi ( 1 , 10000 ) )

# Hàm bình phương số_list bằng vòng lặp
chắc chắn hình vuông_using_loop ( danh sách số ) :
kết quả vuông = [ ]
trên một TRONG danh sách số:
Square_result. nối thêm ( trên một ** 2 )
trở lại kết quả vuông
# Hàm lọc số chẵn_danh sách bằng vòng lặp
chắc chắn filter_even_using_loop ( danh sách số ) :
filter_result = [ ]
trên một TRONG danh sách số:
nếu như trên một % 2 == 0 :
filter_result. nối thêm ( trên một )
trở lại filter_result
# Hàm sắp xếp danh sách số bằng vòng lặp
chắc chắn sắp xếp_sử dụng_loop ( danh sách số ) :
trở lại sắp xếp ( danh sách số )
# Đo thời gian để bình phương số_list sử dụng map()
bản đồ_thời gian = tt. Hiện tôi ( lambda : danh sách ( bản đồ ( lambda x:x** 2 , danh sách số ) ) , con số = 1000 )
# Đo thời gian lọc số chẵn_list bằng filter()
bộ lọc_thời gian = tt. Hiện tôi ( lambda : danh sách ( lọc ( lambda x: x % 2 == 0 , danh sách số ) ) , con số = 1000 )
# Đo thời gian sắp xếp dãy số_list bằng cách sử dụng Sort()
đã sắp xếp_time = tt. Hiện tôi ( lambda : sắp xếp ( danh sách số ) , con số = 1000 )
# Đo thời gian để bình phương số_list bằng vòng lặp
loop_map_time = tt. Hiện tôi ( lambda : hình vuông_using_loop ( danh sách số ) , con số = 1000 )
# Đo thời gian lọc số chẵn_list bằng vòng lặp
loop_filter_time = tt. Hiện tôi ( lambda : filter_even_using_loop ( danh sách số ) , con số = 1000 )
# Đo thời gian sắp xếp dãy số_list bằng vòng lặp
loop_sorted_time = tt. Hiện tôi ( lambda : sắp xếp_USE_loop ( danh sách số ) , con số = 1000 )
in ( 'Danh sách số chứa 10000 phần tử' )
in ( f 'Thời gian bản đồ(): {map_time:.6f} giây' )
in ( f 'Thời gian của Filter(): {filter_time:.6f} giây' )
in ( f 'Đã sắp xếp() Thời gian: {sorted_time:.6f} giây' )
in ( f 'Thời gian vòng lặp (Bản đồ): {loop_map_time:.6f} giây' )
in ( f 'Thời gian vòng lặp (Bộ lọc): {loop_filter_time:.6f} giây' )
in ( f 'Thời gian vòng lặp (Đã sắp xếp): {loop_sorted_time:.6f} giây' )

Chúng ta có thể nhận thấy rằng các hàm dựng sẵn (map(), filter() vàsort()) nhanh hơn các vòng lặp tùy chỉnh cho các tác vụ phổ biến này. Các hàm dựng sẵn trong Python cung cấp một cách tiếp cận ngắn gọn và dễ hiểu hơn để thực hiện các tác vụ này và được tối ưu hóa cao về hiệu suất.

Tối ưu hóa các vòng lặp

Nếu việc viết các vòng lặp là cần thiết thì có một số kỹ thuật mà chúng ta có thể thực hiện để tăng tốc chúng. Nói chung, vòng lặp range() nhanh hơn vòng lặp ngược. Điều này là do range() tạo ra một trình lặp mà không đảo ngược danh sách, đây có thể là một hoạt động tốn kém đối với các danh sách dài. Ngoài ra, vì range() không tạo danh sách mới trong bộ nhớ nên nó sử dụng ít bộ nhớ hơn.

OptimizeLoop.py:

nhập khẩu Hiện tôi BẰNG tt
# Danh sách mẫu_list
danh sách số = danh sách ( phạm vi ( 1 , 100000 ) )
# Hàm duyệt danh sách theo thứ tự ngược lại
chắc chắn loop_reverse_iteration ( ) :
kết quả_reverse = [ ]
j TRONG phạm vi ( chỉ một ( danh sách số ) - 1 , - 1 , - 1 ) :
result_reverse. nối thêm ( danh sách số [ j ] )
trở lại kết quả_reverse
# Hàm lặp danh sách sử dụng range()
chắc chắn loop_range_iteration ( ) :
phạm vi kết quả = [ ]
k TRONG phạm vi ( chỉ một ( danh sách số ) ) :
result_range. nối thêm ( danh sách số [ k ] )
trở lại phạm vi kết quả
# Đo thời gian cần thiết để thực hiện phép lặp ngược
thời gian đảo ngược = tt. Hiện tôi ( loop_reverse_iteration , con số = 1000 )
# Đo thời gian cần thiết để thực hiện lặp phạm vi
phạm vi_thời gian = tt. Hiện tôi ( loop_range_iteration , con số = 1000 )
in ( 'Danh sách số chứa 100000 bản ghi' )
in ( f 'Thời gian lặp lại ngược: {reverse_time:.6f} giây' )
in ( f 'Thời gian lặp phạm vi: {range_time:.6f} giây' )

Tránh các lệnh gọi hàm không cần thiết

Có một số phí tổn mỗi khi một hàm được gọi. Mã chạy nhanh hơn nếu tránh được các lệnh gọi hàm không cần thiết. Ví dụ: thay vì thực hiện lặp đi lặp lại một hàm tính toán một giá trị, hãy thử lưu trữ kết quả của phép tính vào một biến và sử dụng nó.

Công cụ lập hồ sơ

Để tìm hiểu thêm về hiệu suất mã của bạn, ngoài tính năng lập hồ sơ tích hợp, chúng tôi có thể sử dụng các gói lập hồ sơ bên ngoài như cProfile, Pyflame hoặc SnakeViz.

Kết quả bộ nhớ đệm

Nếu mã của chúng tôi cần thực hiện các phép tính tốn kém, chúng tôi có thể cân nhắc việc lưu kết quả vào bộ nhớ đệm để tiết kiệm thời gian.

Lập trình lại

Tái cấu trúc mã để dễ đọc và bảo trì hơn đôi khi là một phần cần thiết trong việc tối ưu hóa mã. Một chương trình nhanh hơn cũng có thể sạch hơn.

Sử dụng Trình biên dịch đúng lúc (JIT)

Các thư viện như PyPy hoặc Numba có thể cung cấp trình biên dịch JIT có thể tăng tốc đáng kể một số loại mã Python nhất định.

Nâng cấp Python

Đảm bảo rằng bạn đang sử dụng phiên bản Python mới nhất vì các phiên bản mới hơn thường bao gồm các cải tiến về hiệu suất.

Song song và đồng thời

Đối với các quy trình có thể song song, hãy điều tra các kỹ thuật song song và đồng bộ hóa như đa xử lý, phân luồng hoặc không đồng bộ.

Hãy nhớ rằng việc đo điểm chuẩn và lập hồ sơ phải là động lực chính của việc tối ưu hóa. Tập trung vào việc cải thiện các vùng mã của chúng tôi có ảnh hưởng đáng kể nhất đến hiệu suất và liên tục kiểm tra các cải tiến của bạn để đảm bảo rằng chúng có tác dụng mong muốn mà không gây ra nhiều lỗi hơn.

Phần kết luận

Tóm lại, tối ưu hóa mã Python là rất quan trọng để cải thiện hiệu suất và hiệu quả tài nguyên. Các nhà phát triển có thể tăng đáng kể tốc độ thực thi và khả năng phản hồi của các ứng dụng Python bằng nhiều kỹ thuật khác nhau như chọn cấu trúc dữ liệu phù hợp, tận dụng các hàm tích hợp, giảm các vòng lặp bổ sung và quản lý bộ nhớ một cách hiệu quả. Việc đo điểm chuẩn và lập hồ sơ liên tục phải định hướng các nỗ lực tối ưu hóa, đảm bảo rằng các tiến bộ về mã phù hợp với yêu cầu về hiệu suất trong thế giới thực. Để đảm bảo sự thành công lâu dài của dự án và giảm nguy cơ phát sinh các vấn đề mới, việc tối ưu hóa mã phải liên tục được cân bằng với các mục tiêu về khả năng đọc và bảo trì mã.