[英]How to optimize the code and reduce memory usage Python
目的是減少memory 的使用。 這意味着它應該以hash
等於test hash
的方式進行優化。
到目前為止我已經嘗試過:
__slots__
但它沒有進行任何更改。float64
更改為float32
。 雖然它顯着減少了內存使用,但它通過更改 hash 來阻止測試。np.array
減少了 CPU 時間: from 13 s to 2.05 s
,但不影響memory 的使用。要重現的代碼:
rows = 40000000
trs = 10
random.seed(42)
generated_data: tp.List[float] = np.array([random.random() for _ in range(rows)])
def df_upd(df_initial: pd.DataFrame, df_new: pd.DataFrame) -> pd.DataFrame:
return pd.concat((df_initial, df_new), axis=1)
class T:
"""adding a column of random data"""
__slots__ = ['var']
def __init__(self, var: float):
self.var = var
def transform(self, df_initial: pd.DataFrame) -> pd.DataFrame:
return df_upd(df_initial, pd.DataFrame({self.var: generated_data}))
class Pipeline:
__slots__ = ['df', 'transforms']
def __init__(self):
self.df = pd.DataFrame()
self.transforms = np.array([T(f"v{i}") for i in range(trs)])
def run(self):
for t in self.transforms:
self.df = t.transform(self.df)
return self.df
if __name__ == "__main__":
# starting the monitoring
tracemalloc.start()
# function call
pipe = Pipeline()
%time df = pipe.run()
print("running")
# displaying the memory
current, peak = tracemalloc.get_traced_memory()
print(f"Current memory usage is {current / 10**3} KB ({(current / 10**3)*0.001} MB); Peak was {peak / 10**3} KB ({(peak / 10**3)*0.001} MB); Diff = {(peak - current) / 10**3} KB ({((peak - current) / 10**3)*0.001} MB)")
# stopping the library
tracemalloc.stop()
# should stay unchanged
%time hashed_df = hashlib.sha256(pd.util.hash_pandas_object(df, index=True).values).hexdigest()
print("hashed_df", hashed_df)
assert hashed_df == test_hash
print("Success!")
如果您避免pd.concat()
並使用增強數據幀的首選方式:
df["new_col_name"] = new_col_data
這將顯着減少峰值 memory 的消耗。
在您的代碼中修復Transform
class 就足夠了:
class Transform:
"""adding a column of random data"""
__slots__ = ['var']
def __init__(self, var: str):
self.var = var
def transform(self, df: pd.DataFrame) -> pd.DataFrame:
df[self.var] = generated_data
return df
(請注意,我還將var
的type
從float
更改為str
以反映它在代碼中的使用方式)。
在我的機器中,我從:
當前 memory 使用量為 1600110.987 KB (1600.110987 MB); 峰值為 4480116.325 KB (4480.116325 MB); 差異 = 2880005.338 KB (2880.005338 MB)
到:
當前 memory 使用量為 1760101.105 KB (1760.101105 MB); 峰值為 1760103.477 KB (1760.1034769999999 MB); 差異 = 2.372 KB (0.002372 MB)
(我不確定為什么在這種情況下當前 memory 的使用率略高)。
為了加快計算速度,您可能需要進行一些預分配。
為此,您可以在 Pipeline 的__init__()
中替換:
self.df = pd.DataFrame()
和:
self.df = pd.DataFrame(data=np.empty((rows, trs)), columns=[f"v{i}" for i in range(trs)])
如果你想變得更快,你可以立即在管道的__init__
中計算 DataFrame ,例如:
class Pipeline:
__slots__ = ['df', 'transforms']
def __init__(self):
self.df = pd.DataFrame(data=generated_data[:, None] + np.zeros(trs)[None, :], columns=[f"v{i}" for i in range(trs)])
def run(self):
return self.df
但我假設你的Transform
是一個更復雜操作的代理,我不確定這種簡化是否容易適應問題中的玩具代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.