简短答案
只有roix数组是c_contiguous.因此,从内存到CPU的总线传输比非连续数据传输更快(由于总线将数据按块移动并缓存)
通过使其成为C连续的np.save(file,np.asarray(a,order =’C’)),您可以进行一些改进(roiz约为5%,roiy约为40%)
更多说明
剖析
您应该使用timeit来计时表演而不是自定义方法.
我已经为您展示了这些示例:
在一个单元格中,我们得到:
import os
import numpy as np
import time
import matplotlib.pyplot as plt
# take a slice of the data
def slice_data(roi):
dic = {}
data = np.zeros((512,512,256))
dic['data'] = np.squeeze( data[roi[0]:roi[1]+1, roi[2]:roi[3]+1, roi[4]:roi[5]+1] )
return dic
# save slices if the data
def save_slices(roi, save=False):
var = 'data'
for i in range(0,6):
# iterate to simulate a time series of data
a = slice_data(roi)[var]
var_dir = 'save_test/'
if not os.path.exists(var_dir): os.makedirs(var_dir)
file = var_dir + '{0:04d}{1}'.format(i,'.npy')
if save is True:
np.save(file, a)
## define slices
roix=[256, 256, 0, 512, 0, 256] # yz plane slice
roiy=[0, 512, 256, 256, 0, 256] # xz plane slice
roiz=[0, 512, 0, 512, 128, 128] # xy plane slice
在其他方面:
%%timeit -n 100
save_slices(roix) # 19.8 ms ± 285 ?s per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit -n 100
save_slices(roiy) # 20.5 ms ± 948 ?s per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit -n 100
save_slices(roiz) # 20 ms ± 345 ?s per loop (mean ± std. dev. of 7 runs, 100 loops each)
随着保存
%%timeit -n 10 -r 3
save_slices(roix, True) # 32.7 ms ± 2.31 ms per loop (mean ± std. dev. of 3 runs, 10 loops each)
%%timeit -n 10 -r 3
save_slices(roiy, True) # 101 ms ± 2.61 ms per loop (mean ± std. dev. of 3 runs, 10 loops each)
%%timeit -n 10 -r 3
save_slices(roix, True) # 1.9 s ± 21.1 ms per loop (mean ± std. dev. of 3 runs, 10 loops each)
因此,正如您已经注意到的,在不节省资源的情况下,性能是相同的!
让我们进入np.save()方法
NP保存方法
np.save负责io流,并调用write_array方法.对于C_contigous数组,这确实非常快. (快速访问内存)
让我们验证这个假设:
np.squeeze( np.zeros((512,512,256))[roix[0]:roix[1]+1, roix[2]:roix[3]+1, roix[4]:roix[5]+1] ).flags.c_contiguous # returns True
np.squeeze( np.zeros((512,512,256))[roiy[0]:roiy[1]+1, roiy[2]:roiy[3]+1, roiy[4]:roiy[5]+1] ).flags.c_contiguous # returns False
np.squeeze( np.zeros((512,512,256))[roiz[0]:roiz[1]+1, roiz[2]:roiz[3]+1, roiz[4]:roiz[5]+1] ).flags.c_contiguous # returns False
因此,这可以解释roix和roiy / roiz之间的区别.
roiy和roiz之间差异的潜在解释.数据传输使程序变慢
在那之后,我只能作个假设,roiz似乎比roiy更加分散. write_array方法要花费很多时间.
我现在无法自己对此进行测试,但是可以使用linux中的perf命令来验证这一部分. (要查看使用的时间总线数量,例如高速缓存未命中的数量).
如果我必须做一个大胆的猜测,我会说由于数据不连续而导致高速缓存丢失率很高.因此,将数据从RAM传输到CPU确实减慢了该过程.
处理存储的其他方式