Sử dụng bộ nhớ Python của mảng numpy


156

Tôi đang sử dụng python để phân tích một số tệp lớn và tôi đang gặp vấn đề về bộ nhớ, vì vậy tôi đã sử dụng sys.getsizeof () để thử và theo dõi việc sử dụng, nhưng hành vi của nó với các mảng khó hiểu là kỳ quái. Dưới đây là một ví dụ liên quan đến bản đồ các suất phản chiếu mà tôi phải mở:

>>> import numpy as np
>>> import struct
>>> from sys import getsizeof
>>> f = open('Albedo_map.assoc', 'rb')
>>> getsizeof(f)
144
>>> albedo = struct.unpack('%df' % (7200*3600), f.read(7200*3600*4))
>>> getsizeof(albedo)
207360056
>>> albedo = np.array(albedo).reshape(3600,7200)
>>> getsizeof(albedo)
80

Chà, dữ liệu vẫn còn đó, nhưng kích thước của đối tượng, bản đồ 3600x7200 pixel, đã tăng từ ~ 200 Mb đến 80 byte. Tôi muốn hy vọng rằng các vấn đề về trí nhớ của tôi đã kết thúc và chỉ chuyển đổi mọi thứ thành các mảng khó chịu, nhưng tôi cảm thấy rằng hành vi này, nếu đúng, theo một cách nào đó sẽ vi phạm một số định luật về lý thuyết thông tin hoặc nhiệt động lực học, hoặc một cái gì đó, vì vậy tôi có xu hướng tin rằng gotizeof () không hoạt động với các mảng numpy. Có ý kiến ​​gì không?


8
Từ các tài liệu trên sys.getsizeof: "Trả về kích thước của một đối tượng theo byte. Đối tượng có thể là bất kỳ loại đối tượng nào. Tất cả các đối tượng tích hợp sẽ trả về kết quả chính xác, nhưng điều này không phải đúng với các tiện ích mở rộng của bên thứ ba vì nó là thực hiện cụ thể. Chỉ có mức tiêu thụ bộ nhớ được gán trực tiếp cho đối tượng, chứ không phải mức tiêu thụ bộ nhớ của các đối tượng mà nó đề cập đến. "
Joel Cornett

1
Điều này làm cho getsizeofmột chỉ số không đáng tin cậy về mức tiêu thụ bộ nhớ, đặc biệt là các tiện ích mở rộng của bên thứ 3.
Joel Cornett

13
Về cơ bản, vấn đề ở đây resizelà trả về một view, không phải là một mảng mới. Bạn đang nhận được kích thước của chế độ xem, không phải dữ liệu thực tế.
mgilson

Cuối cùng, sys.getsizeof(albedo.base)sẽ cho kích thước của chế độ không xem.
Eric

Câu trả lời:


236

Bạn có thể sử dụng array.nbytescho các mảng numpy, ví dụ:

>>> import numpy as np
>>> from sys import getsizeof
>>> a = [0] * 1024
>>> b = np.array(a)
>>> getsizeof(a)
8264
>>> b.nbytes
8192

Sys.getsizeof (a) của nó, sau khi thực hiện nhập sys.
eddys

2
b.__sizeof__()tương đương vớisys.getsizeof(b)
palash

1
round(getsizeof(a) / 1024 / 1024,2)để nhận MB
gies0r

13

Trường nbyte sẽ cung cấp cho bạn kích thước tính theo byte của tất cả các phần tử của mảng trong numpy.array:

size_in_bytes = my_numpy_array.nbytes

Lưu ý rằng điều này không đo lường "các thuộc tính không phải là thành phần của đối tượng mảng", vì vậy kích thước thực tế tính bằng byte có thể lớn hơn vài byte so với giá trị này.


Câu trả lời này vẫn tạo ra một mảng, vì vậy tôi nghĩ bạn có nghĩa là "không cần phải chuyển đổi từ danh sách sang mảng". Mặc dù đúng là câu trả lời của GWW trước tiên tạo ra một danh sách và sau đó chuyển đổi nó thành một mảng, bên cạnh đó, vì OP đã có một mảng ... Vấn đề là làm thế nào để có được kích thước của một mảng numpy, vì vậy nó không phải là quan trọng làm thế nào bạn có được mảng ở nơi đầu tiên. Người ta có thể chỉ trích tương tự câu trả lời này bằng cách nói rằng nó định hình lại một mảng hiện có.
Moot

Xin chào @Moot, cảm ơn vì nhận xét. Câu hỏi là làm thế nào để có được kích thước tính theo byte của một mảng. Mặc dù đúng là đoạn mã của tôi trước tiên tạo ra một mảng, nhưng nó chỉ nhằm mục đích có một ví dụ hoàn chỉnh có thể được thực thi. Tôi sẽ chỉnh sửa câu trả lời của tôi để nhấn mạnh điều này.
El Marce

1

Trong máy tính xách tay python Tôi thường muốn lọc ra 'lơ lửng' numpy.ndarray's, đặc biệt là những người mà được lưu trữ trong _1, _2, vv mà không bao giờ thực sự có nghĩa là để ở còn sống.

Tôi sử dụng mã này để có được một danh sách của tất cả chúng và kích thước của chúng.

Không chắc chắn nếu locals()hoặc globals()là tốt hơn ở đây.

import sys
import numpy
from humanize import naturalsize

for size, name in sorted(
    (value.nbytes, name)
    for name, value in locals().items()
    if isinstance(value, numpy.ndarray)):
  print("{:>30}: {:>8}".format(name, naturalsize(size)))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.