【发布时间】:2019-03-14 16:11:13
【问题描述】:
我有 50000+ 个 npz 文件(文件大小 15MB),每个文件都有三个 numpy 数组 A、B、C。
A 是一个形状为 (33000,) 的 numpy 数组; B 是一个形状为 (33000,) 的 numpy 数组,C 是一个形状为 (33000,224,224) 的 uint8 类型的位数组。
npz_file_dict = np.load(npz_file_path)
num_records = len(npz_file_dict['A'])
A = npz_file_dict['A']
B = npz_file_dict['B']
C = npz_file_dict['C']
def get_items(num_records):
for i in range(num_records)
yield A[i], B[i], C[i]
for a,b,c in get_items(num_records):
# do some work with (a,b,c)
# store the result in a json format with {'a' : a, 'b' : b, 'c' : c}
for 循环需要很长时间才能完成(对于 30000 条记录,有时需要超过 35 分钟)。有没有一种有效的方法来解析记录?
编辑:我尝试做内存映射的 numpy 数组,但它似乎并没有提高性能,因为它们只对 npy 文件有影响。
编辑:需要对我提出的方法进行批评。
我已经求助于使用内存映射来加速我的迭代,对于我读取的每个文件,我都会花费一些时间(在我所谓的设置阶段)将这个巨大的 numpy 数组映射到文件指针。
num_records = len(npz_file_dict['np_cids'])
print(num_records)
start_memmap = time()
data = npz_file_dict['C']
print('Time to read data {}'.format(time() - start_memmap))
filename = path.join(mkdtemp(), 'newfile.dat')
print('Path to file', filename)
fp = np.memmap(filename, dtype='float32', mode='w+', shape=(num_records, 224,224))
fp[:] = data[:]
finish_memmap = time()
print('Time to create memmap {}'.format(finish_memmap - start_memmap))
完成此设置后,我只需在 for 循环中遍历 A 和 B 数组并使用 fp 获取相应的 i^th 记录。这种方法的优点是迭代非常快。缺点是设置时间介于单进程模式下的 50 秒和多进程模式下的 100 秒之间。
如果您将设置时间摊销到 30000 条记录的集合中,则大约是 3.3 毫秒。在迭代过程中,读取速度非常快——几百微秒。这使得每条记录所花费的总时间大约为 5 毫秒。与我之前的方法(每条记录需要 150 毫秒)相比,这是 96% 的速度。
【问题讨论】:
-
npz_file_dict['A']是一个数组。其他名称也一样。为了澄清这一点,请从A = npz_file_dict['A']等开始。无论来源如何,对数组元素的迭代都很慢。如果您想要速度,您需要使用“整个”阵列,而不是一次只有一个“记录”。但是你没有告诉我们“一些工作”是什么,所以我们帮不上什么忙。逐条创建json条目也会很慢。 -
你会考虑使用多处理模块docs.python.org/2/library/multiprocessing.html吗?或者您是否正在寻找一种矩阵数学解决方案来加快速度?
-
如果不做任何处理就运行需要多长时间,例如
def somework(a, b, c):pass?如果瓶颈在这里,或者在你正在做的处理中,这会给你一个好主意。
标签: python arrays json file numpy