반응형

sys.getdizeof 메소드와 NumPy배열의 nbytes 속성을 사용하여 Numpy 배열의 크기를 확인해봤습니다.

2022. 01. 22  최초작성




동적으로 크기를 늘릴 수 있는  Python의 리스트와 달리 NumPy 배열을 생성하면 고정된 크기를 갖습니다. 

또한 여러가지 데이터 타입의 원소를 가질 수 있는 Python의 리스트와 달리 NumPy 배열의 모든 원소는 동일한 데이터 타입이어야 합니다. 

따라서 메모리 상에 저장된 NumPy 배열의 원소들의 크기는 모두 동일합니다.



NumPy 배열에 여러가지 데이터 타입의 값을 넣어보면 에러가 나지 않지만 NumPy 배열의 데이터 타입을 확인해보면 원소들을 모두 포함할 수 있는 데이터 타입으로 되어 있는 것을 볼 수 있습니다.

 

>>> a = np.array([1, 'hello', 0.1])

>>> a

array(['1', 'hello', '0.1'], dtype='<U32')



데이터 타입으로 지정된 <U32의 의미는 32개의 문자로 구성된 리틀 엔디안 유니코드 문자열이라는 의미입니다. 자세한 내용은 링크

https://stackoverflow.com/a/56944839 를 확인하세요.



NumPy 배열의 nbytes 속성은  저장된 데이터의 크기를 반환하고 sys.getsizeof 메소드는  오버헤드(overhead)가 포함된 NumPy 배열의 전체 크기를 반환합니다. 오버헤드는 NumPy 배열에 저장된 데이터를 위한 정보(배열 차원, 데이터 타입 등) 때문입니다. NumPy 배열이 클래스이기 때문에 추가되는 정보도 더 있을거라 예상됩니다. 원소가 없는 비어있는 넘파이 배열을 getsizeof로 확인해보면 할당된 메모리가 있는데 이것이 오버헤드를 위한 것입니다. 

 

NumPy 배열에 원소가 추가되면 비어있는 넘파이 배열에 할당된 크기에 추가된 원소 개수 * 원소 타입 크기만큼 메모리가 추가됩니다. 넘파이 배열이 커져도 비어있는 넘파이 배열에 할당되었던 크기는 유지됩니다.



NumPy 배열의 nbytes 속성과 sys.getsizeof 메소드를 테스트한 코드입니다. 



import sys
import numpy as np


numpy_array_empty = np.array([])
numpy_array_empty_float32 = np.array([], dtype=np.float32)
numpy_array_empty_int8 = np.array([], dtype=np.int8)
numpy_array_one = np.array([3])
numpy_array_one_float32 = np.array([3], dtype=np.float32)
numpy_array_one_int8 = np.array([3], dtype=np.int8)
numpy_array_10 = np.arange(10)
numpy_array_10_int8 = np.arange(10, dtype=np.int8) 


print("numpy_array_empty (", numpy_array_empty.dtype, ") -> ", "nbytes", numpy_array_empty.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_empty))
print("numpy_array_empty_float32 (", numpy_array_empty_float32.dtype, ") -> ", "nbytes", numpy_array_empty_float32.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_empty_float32))
print("numpy_array_empty_int8 (", numpy_array_empty_int8.dtype, ") -> ", "nbytes", numpy_array_empty_int8.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_empty_int8))
print("numpy_array_one (", numpy_array_one.dtype, ") -> ", "nbytes", numpy_array_one.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_one), "diff", sys.getsizeof(numpy_array_one)-sys.getsizeof(numpy_array_empty))
print("numpy_array_one_float32 (", numpy_array_one_float32.dtype, ") -> ", "nbytes", numpy_array_one_float32.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_one_float32), "diff", sys.getsizeof(numpy_array_one_float32)-sys.getsizeof(numpy_array_empty_float32))
print("numpy_array_one_int8 (", numpy_array_one_int8.dtype, ") -> ", "nbytes", numpy_array_one_int8.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_one_int8), "diff", sys.getsizeof(numpy_array_one_int8)-sys.getsizeof(numpy_array_empty_int8))
print("numpy_array_10 (", numpy_array_10.dtype, ") -> ", "nbytes", numpy_array_10.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_10), "diff", sys.getsizeof(numpy_array_10)-sys.getsizeof(numpy_array_empty))
print("numpy_array_10_int8 (", numpy_array_10_int8.dtype, ") -> ", "nbytes", numpy_array_10_int8.nbytes,
                    "getsizeof", sys.getsizeof(numpy_array_10_int8), "diff", sys.getsizeof(numpy_array_10_int8)-sys.getsizeof(numpy_array_empty_int8))
# numpy_array_empty ( float64 ) ->  nbytes 0 getsizeof 104
# numpy_array_empty_float32 ( float32 ) ->  nbytes 0 getsizeof 104
# numpy_array_empty_int8 ( int8 ) ->  nbytes 0 getsizeof 104
# numpy_array_one ( int64 ) ->  nbytes 8 getsizeof 112 diff 8
# numpy_array_one_float32 ( float32 ) ->  nbytes 4 getsizeof 108 diff 4
# numpy_array_one_int8 ( int8 ) ->  nbytes 1 getsizeof 105 diff 1
# numpy_array_10 ( int64 ) ->  nbytes 80 getsizeof 184 diff 80
# numpy_array_10_int8 ( int8 ) ->  nbytes 10 getsizeof 114 diff 10



실행 결과를 살펴보겠습니다. 

사용한 운영체제 또는 Python 버전 등에 따라 포스트의 결과와 다를 수 있습니다. 

 

포스트에서 사용한 환경은 다음과 같습니다. 

 

macOS Monterey 12.1

Python 3.8.11 64bit

NumPy 1.21.4



비어있는 NumPy 배열의 경우 nbytes 속성값은 0 바이트 , sys.getsizeof 메소드의 값은 104 바이트로 동일합니다.

 

numpy_array_empty ( float64 ) ->  nbytes 0 getsizeof 104

numpy_array_empty_float32 ( float32 ) ->  nbytes 0 getsizeof 104

numpy_array_empty_int8 ( int8 ) ->  nbytes 0 getsizeof 104



원소를 하나씩 추가해보면 추가한 원소의 데이터 타입 크기 만큼 바이트 수가 증가합니다. 

 

numpy_array_one ( int64 ) ->  nbytes 8 getsizeof 112 diff 8

numpy_array_one_float32 ( float32 ) ->  nbytes 4 getsizeof 108 diff 4

numpy_array_one_int8 ( int8 ) ->  nbytes 1 getsizeof 105 diff 1



원소를 10개씩 추가해보면 추가한 원소의 데이터 타입 크기 * 10  만큼 바이트 수가 증가합니다. 

 

numpy_array_10 ( int64 ) ->  nbytes 80 getsizeof 184 diff 80

numpy_array_10_int8 ( int8 ) ->  nbytes 10 getsizeof 114 diff 10




참고



https://community.dataquest.io/t/ndarray-nbytes-vs-sys-getsizeof-ndarray/547939

 

https://stackoverflow.com/questions/35421869/nbytes-and-getsizeof-return-different-values

 

https://www.reddit.com/r/learnpython/comments/9cp9id/understanding_memory_in_python/




반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts