/ / Cách tìm cấu hình tiêu thụ bộ nhớ của mã Python của bạn

Cách tìm cấu hình tiêu thụ bộ nhớ của mã Python của bạn

Vì “có nhiều cách để thực hiện” trong Python, nên việc tìm ra cách tiếp cận hiệu quả nhất về bộ nhớ cho một số tác vụ có thể là một thách thức. Đây là nơi mà một hồ sơ bộ nhớ có thể giúp đỡ. Cũng như theo dõi rò rỉ, việc ước tính cấu hình bộ nhớ mã của bạn giúp xác định mã nào sử dụng bộ nhớ hiệu quả.



Cho dù bạn đang phát triển mô hình máy học hay trang web bằng Python, bạn có thể ước tính cấu hình bộ nhớ cho tập lệnh, dòng mã riêng lẻ hoặc chức năng.



Ước tính cấu hình bộ nhớ của toàn bộ cơ sở mã của bạn có thể không thực tế, vì điều này có thể làm chậm đáng kể ứng dụng của bạn. Thay vào đó, tốt nhất là bạn nên lập hồ sơ có chọn lọc các chức năng hoặc phương thức mà bạn nghi ngờ có thể đang tiêu tốn nhiều bộ nhớ hơn. Nhưng ngay cả khi bạn muốn làm điều này cho toàn bộ ứng dụng của mình, bạn có thể muốn dành một mô-đun biệt lập để xử lý nó.

Có rất nhiều thư viện lược tả trong Python. Một số phổ biến nhất là memory_profiler, psutil, Tracemallocngười thổi sáo. Hướng dẫn này sử dụng memory_profiler psutil.

Trong khi psutil là lý tưởng để ước tính tổng mức tiêu thụ bộ nhớ của một phương thức hoặc chức năng thực thi, memory_profiler cung cấp thông tin sử dụng bộ nhớ chi tiết hơn, bao gồm xu hướng sử dụng cấp độ chức năng và từng dòng theo thời gian.

Để bắt đầu, hãy cài đặt memory_profiler vào môi trường ảo Python của bạn. Điều này cũng cài đặt psutil.

 pip install memory_profiler

Lấy kích thước của một đối tượng trong bộ nhớ

Bạn có thể bắt đầu lập hồ sơ bộ nhớ của mình bằng cách trước tiên tính toán kích thước của một đối tượng mà bạn định sử dụng trong bộ nhớ.

Loại lược tả này rất hữu ích khi bắt đầu phát triển—trong khi cố gắng xác định loại đối tượng nào sẽ được sử dụng trong một chương trình.

Ví dụ: nếu bạn gặp khó khăn khi quyết định sử dụng phương thức nào để đạt được một tác vụ, chẳng hạn như loại dữ liệu Python thích hợp, bạn có thể lấy kích thước của từng byte để xác định phương thức nào nhẹ hơn cho trường hợp sử dụng của bạn.

Các sys.getsizeof phương pháp tích hợp có ích ở đây:

 import sys
print(f"list size: {sys.getsizeof([])} bytes")
print(f"dictionary size: {sys.getsizeof(dict)} bytes")
print(f"tuple size: {sys.getsizeof(())} bytes")
print(f"set size: {sys.getsizeof({})} bytes")

Đây là đầu ra:

Hồ sơ bộ nhớ cho các loại dữ liệu

Bạn cũng có thể sử dụng sys.getsizeof phương pháp để so sánh kích thước bộ nhớ của chức năng tích hợp và chức năng tùy chỉnh.

Ví dụ: so sánh hàm độ dài tùy chỉnh sử dụng vòng lặp Python for này với hàm tích hợp sẵn len chức năng:

 import sys

def getLength(iterable):
    count = 0

    for i in iterable:
        count +=1

    return count

print(f"Built-in length function: {sys.getsizeof(len)} bytes")
print(f"Custom length function: {sys.getsizeof(getLength)} bytes")

Đoạn mã trên cho kết quả như sau:

so sánh bộ nhớ đầu ra dòng lệnh

Tuy nhiên, trong khi sys.getsizeof đo kích thước của một đối tượng trong bộ nhớ, nó chỉ chiếm chính đối tượng đó chứ không phải những đối tượng tham chiếu đến nó. Đối với điều đó, bạn sẽ cần một phương pháp lập hồ sơ chi tiết hơn.

Tìm hồ sơ bộ nhớ của hàm Python

Bạn có thể nhận được cấu hình bộ nhớ chi tiết hơn của từng dòng mã của hàm bằng cách sử dụng memory_profiler bưu kiện. Điều này liên quan đến việc thêm các @hồ sơ trang trí cho chức năng hoặc phương pháp của bạn:

 import pandas
import numpy
from memory_profiler import profile

class Manipulate:
    @profile
    def manipulateData(self):
        df = pandas.DataFrame({
            'A' :[0, 3, numpy.nan, 10, 3, numpy.nan],
            'B' : [numpy.nan, "Pandas", numpy.nan, "Pandas", "Python", "JavaScript"],
        })

        df.fillna(method='bfill', inplace=True)
        df.fillna(method='ffill', inplace=True)
        return str(df)

manip = Manipulate()
print(manip.manipulateData())

Đoạn mã trên cung cấp cấu hình bộ nhớ chi tiết của từng dòng mã trong hàm như được hiển thị:

Đầu ra mã cho cấu hình bộ nhớ từng dòng

Các mem sử dụng cột cho biết mức sử dụng bộ nhớ cho một dòng mã cụ thể, trong khi Tăng cột hiển thị chi phí đóng góp của mỗi dòng. Các Tần suất xảy ra cột xác định số lần một dòng mã cấp phát hoặc hủy cấp phát bộ nhớ.

Chẳng hạn, trong đầu ra ở trên, dòng 11 xảy ra hai lần với mức tăng bộ nhớ là 0,1 MiB (Mebibyte), tăng mức sử dụng bộ nhớ lên 55,4 MiB. Các dòng 19 và 22 cũng đóng góp lần lượt 0,2 MiB và 0,3 MiB, tổng mức sử dụng bộ nhớ là 55,9 MiB.

Tìm hồ sơ bộ nhớ của tập lệnh Python theo dấu thời gian

Bạn cũng có thể ước tính cấu hình bộ nhớ của toàn bộ tập lệnh Python bằng cách sử dụng memory_profiler bằng cách chạy mprof lệnh trong thiết bị đầu cuối như được hiển thị:

 mprof run script_name.py

Lệnh trên lấy mẫu tập lệnh được chỉ định cứ sau 0,1 giây và tự động tạo một .dat tập tin bên trong thư mục dự án hiện tại của bạn.

Cấu hình bộ nhớ của tập lệnh Python

Các số liệu theo sau MEM ký hiệu là các cấu hình sử dụng bộ nhớ của tập lệnh Python tại một khoảng thời gian cụ thể. Các số cuối cùng bên phải biểu thị dấu thời gian mà trình lược tả đã chụp cho mỗi lần sử dụng bộ nhớ.

Bạn cũng có thể nhận được một biểu đồ của cấu hình bộ nhớ. Điều này yêu cầu cài đặt matplotlib:

 pip install matplotlib

Sau khi cài đặt, hãy chạy chương trình mprof lệnh như vậy:

 mprof plot

Đây là đầu ra trong trường hợp này:

Đầu ra cốt truyện dòng lệnh-1

Chạy Hồ sơ bộ nhớ tập lệnh trong tệp Python chuyên dụng

Bạn có thể muốn lập hồ sơ cho các tập lệnh Python khác nhau. Bạn có thể thực hiện việc này bằng mô-đun Python chuyên dụng qua Python’s quy trình con.

Bằng cách này, bạn có thể tách trình lược tả bộ nhớ khỏi cơ sở mã của mình và lưu cục bộ đầu ra biểu đồ:

 import subprocess

subprocess.run([
    'mprof', 'run', '--include-children', 'missing.py'
])


subprocess.run(['mprof', 'plot', '--output=output.jpg'])

Để chạy cấu hình bộ nhớ của tập lệnh, bạn chỉ cần chạy tệp Python chứa mã ở trên. Điều này tạo ra một sơ đồ hồ sơ bộ nhớ (đầu ra.jpg) trong thư mục tệp:

Biểu đồ hồ sơ bộ nhớ tập lệnh

Tìm dung lượng bộ nhớ được sử dụng từ một hàm thực thi

Bạn có thể tìm cấu hình bộ nhớ tổng của một phương thức hoặc chức năng trong khi thực hiện bằng cách sử dụng psutil bưu kiện.

Chẳng hạn, để lập hồ sơ phương pháp thao tác Pandas DataFrame trước đó bên trong một tệp Python khác:

 import psutil
import sys
import os
sys.path.append(sys.path[0] + "/..")


from somecode.missing import Manipulate


manip = Manipulate()

process = psutil.Process(os.getpid())
initial_memory = process.memory_info().rss


manip.manipulateData()


final_memory = process.memory_info().rss
memory_consumed = final_memory - initial_memory
memory_consumed_mb = memory_consumed / (1024 * 1024)
print(f"Memory consumed by the function: {memory_consumed_mb:.2f} MB")

Ở trên ước tính tổng cấu hình bộ nhớ của phương thức tính bằng megabyte (MB) như được hiển thị:

Tổng số dòng lệnh đầu ra hồ sơ bộ nhớ

Tìm hồ sơ bộ nhớ của một dòng mã trong Jupyter Notebook

Nếu bạn sử dụng iPython trong Jupyter Notebook, bạn có thể tính toán cấu hình bộ nhớ của một lớp lót bằng cách sử dụng memory_profiler. Bạn chỉ cần tải memory_profiler trong một ô. Sau đó thêm %memit chức năng kỳ diệu cho mã của bạn trong các ô tiếp theo; điều này trả về bộ nhớ cao nhất của mã và kích thước tăng dần.

Phương pháp này không hoạt động với các tập lệnh Python thông thường ngoài iPython trong Jupyter Notebook.

Ví dụ:

Mã máy tính xách tay Jupyter và đầu ra

Bạn cũng có thể sử dụng %memit chức năng ma thuật trong Jypyter Notebook để cấu hình bộ nhớ của chức năng khi chạy:

Cấu hình bộ nhớ chức năng Jupyter Notebook

Cải thiện hiệu quả bộ nhớ trong mã Python của bạn

Xem xét các tác vụ nâng dữ liệu nặng mà chúng tôi thường sử dụng Python, mỗi dòng mã cần tối ưu hóa đầy đủ để quản lý việc sử dụng bộ nhớ. Mặc dù Python có nhiều hàm Python tích hợp, nhưng các đối tượng không được ước tính dẫn đến rò rỉ bộ nhớ.

Nếu bạn đã bỏ mọi cú pháp Python hoạt động vào cơ sở mã của mình mà không xem xét việc sử dụng bộ nhớ, bạn có thể muốn nhìn lại trước khi đi quá xa.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *