将 CSV 文件加载到 NumPy memmap 数组使用太多内存
Posted
技术标签:
【中文标题】将 CSV 文件加载到 NumPy memmap 数组使用太多内存【英文标题】:Loading CSV file to NumPy memmap array uses too much memory 【发布时间】:2019-09-27 12:11:31 【问题描述】:我正在尝试将 4.47GB 的 CSV 文件加载到内存映射的 NumPy 数组中。在具有 85GB RAM 的 GCP 机器上,大约需要 .这样做需要 500 秒,结果是 1.03GB 数组。
问题在于它在上传文件到阵列的过程中消耗了多达 26GB 的 RAM。有没有办法修改以下代码,以便在上传过程中消耗更少的 RAM(如果可能的话,时间)?
import tempfile, numpy as np
def create_memmap_ndarray_from_csv(csv_file): # load int8 csv file to int8 memory-mapped numpy array
with open(csv_file, "r") as f:
rows = len(f.readlines())
with open(csv_file, "r") as f:
cols = len(f.readline().split(','))
memmap_file = tempfile.NamedTemporaryFile(prefix='ndarray', suffix='.memmap')
arr_int8_mm = np.memmap(memmap_file, dtype=np.int8, mode='w+', shape=(rows,cols))
arr_int8_mm = np.loadtxt(csv_file, dtype=np.int8, delimiter=',')
return arr_int8_mm
【问题讨论】:
使用loadtxt
加载csv 后,使用np.save(filename, array)
将文件存储为二进制.npy
文件。然后您可以使用np.load(filename, mmap_mode='r')
加载文件,您将拥有内存消耗最少的 memmap 数组。
您似乎不了解 Python 变量赋值。使用A = fn()
,首先运行fn()
,创建它需要的任何东西。结果被分配给A
(并丢弃之前分配给A
的任何东西)。在您的代码中arr_int8_mm
是loadtxt
创建的数组,而不是memmap。
loadtxt
逐行读取文件,收集列表列表(实际上是您的readlines
和split
)。最后,它从结果中创建一个数组。可以想象,您自己的阅读器可以一次拆分一行,并将结果数组写入memmap
的一行。
【参考方案1】:
我已根据 cmets 将代码修改为原始问题。更新后的代码使用更少的内存:8GB 而不是 26GB。 loadtext, readline, split
方法进一步减少了内存的使用,但速度太慢了。
import tempfile, numpy as np, pandas as pd
def create_ndarray_from_csv(csv_file): # load csv file to int8 normal/memmap ndarray
df_int8 = pd.read_csv(csv_file, dtype=np.int8, header=None)
arr_int8 = df_int8.values
del df_int8
memmap_file = tempfile.NamedTemporaryFile(prefix='ndarray-memmap', suffix='.npy')
np.save(memmap_file.name, arr_int8)
del arr_int8
arr_mm_int8 = np.load(memmap_file.name, mmap_mode='r')
return arr_mm_int8
【讨论】:
以上是关于将 CSV 文件加载到 NumPy memmap 数组使用太多内存的主要内容,如果未能解决你的问题,请参考以下文章
如何将 CSV 文件中的数据加载到 numpy 数组中[重复]
python 内存映射的`npz`文件解决方法。 `numpy.load(npzfile,memmap_mode ='r')`忽略`memmap_mode`选项。这是一种解决方法