Giảm mức sử dụng bộ nhớ trong Python là rất khó, vì Python không thực sự giải phóng bộ nhớ trở lại hệ điều hành . Nếu bạn xóa các đối tượng, thì bộ nhớ sẽ có sẵn cho các đối tượng Python mới, nhưng không free()
quay lại hệ thống ( xem câu hỏi này ).
Nếu bạn dính vào các mảng số, chúng sẽ được giải phóng, nhưng các đối tượng đóng hộp thì không.
>>> import os, psutil, numpy as np
>>> def usage():
... process = psutil.Process(os.getpid())
... return process.get_memory_info()[0] / float(2 ** 20)
...
>>> usage() # initial memory usage
27.5
>>> arr = np.arange(10 ** 8) # create a large array without boxing
>>> usage()
790.46875
>>> del arr
>>> usage()
27.52734375 # numpy just free()'d the array
>>> arr = np.arange(10 ** 8, dtype='O') # create lots of objects
>>> usage()
3135.109375
>>> del arr
>>> usage()
2372.16796875 # numpy frees the array, but python keeps the heap big
Giảm số lượng khung dữ liệu
Python giữ cho bộ nhớ của chúng ta ở hình mờ cao, nhưng chúng ta có thể giảm tổng số khung dữ liệu mà chúng ta tạo. Khi sửa đổi khung dữ liệu của bạn inplace=True
, bạn không nên tạo bản sao.
Một lỗi phổ biến khác đang giữ bản sao của các khung dữ liệu đã tạo trước đó trong ipython:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame({'foo': [1,2,3,4]})
In [3]: df + 1
Out[3]:
foo
0 2
1 3
2 4
3 5
In [4]: df + 2
Out[4]:
foo
0 3
1 4
2 5
3 6
In [5]: Out # Still has all our temporary DataFrame objects!
Out[5]:
{3: foo
0 2
1 3
2 4
3 5, 4: foo
0 3
1 4
2 5
3 6}
Bạn có thể sửa lỗi này bằng cách nhập %reset Out
để xóa lịch sử của mình. Ngoài ra, bạn có thể điều chỉnh lượng lịch sử mà ipython lưu giữ vớiipython --cache-size=5
(mặc định là 1000).
Giảm kích thước khung dữ liệu
Nếu có thể, hãy tránh sử dụng các kiểu đối tượng.
>>> df.dtypes
foo float64 # 8 bytes per value
bar int64 # 8 bytes per value
baz object # at least 48 bytes per value, often more
Các giá trị với loại đối tượng được đóng hộp, có nghĩa là mảng numpy chỉ chứa một con trỏ và bạn có một đối tượng Python đầy đủ trên heap cho mọi giá trị trong khung dữ liệu của bạn. Điều này bao gồm các chuỗi.
Trong khi numpy hỗ trợ các chuỗi có kích thước cố định trong các mảng, thì gấu trúc thì không ( nó khiến người dùng nhầm lẫn ). Điều này có thể tạo ra sự khác biệt đáng kể:
>>> import numpy as np
>>> arr = np.array(['foo', 'bar', 'baz'])
>>> arr.dtype
dtype('S3')
>>> arr.nbytes
9
>>> import sys; import pandas as pd
>>> s = pd.Series(['foo', 'bar', 'baz'])
dtype('O')
>>> sum(sys.getsizeof(x) for x in s)
120
Bạn có thể muốn tránh sử dụng cột chuỗi hoặc tìm cách biểu diễn dữ liệu chuỗi dưới dạng số.
Nếu bạn có khung dữ liệu chứa nhiều giá trị lặp lại (NaN rất phổ biến), thì bạn có thể sử dụng cấu trúc dữ liệu thưa thớt để giảm mức sử dụng bộ nhớ:
>>> df1.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 1 columns):
foo float64
dtypes: float64(1)
memory usage: 605.5 MB
>>> df1.shape
(39681584, 1)
>>> df1.foo.isnull().sum() * 100. / len(df1)
20.628483479893344 # so 20% of values are NaN
>>> df1.to_sparse().info()
<class 'pandas.sparse.frame.SparseDataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 1 columns):
foo float64
dtypes: float64(1)
memory usage: 543.0 MB
Xem mức sử dụng bộ nhớ
Bạn có thể xem việc sử dụng bộ nhớ ( tài liệu ):
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 39681584 entries, 0 to 39681583
Data columns (total 14 columns):
...
dtypes: datetime64[ns](1), float64(8), int64(1), object(4)
memory usage: 4.4+ GB
Đối với pandas 0.17.1, bạn cũng có thể df.info(memory_usage='deep')
xem việc sử dụng bộ nhớ bao gồm các đối tượng.
gc
mô-đun và gọigc.collect()
nhưng nó có thể không khôi phục lại bộ nhớ