您好,我在进行快速矩阵乘法、加法、function_overwrite 和轴缩减求和以及在没有 RAM 的 CPU 上使用 numpy.memmaps 时遇到问题(我认为)。仅当使用 numexpr 时,我才有可能避免从点创建数组。
For example:
a=np.require(np.memmap('a.npy',mode='w+',order='C',dtype=np.float64,shape=(10,1)),requirements=['O'])
b=np.memmap('b.npy',mode='w+',order='C',dtype=np.float64,shape=(1,5))
c=np.memmap('c.npy',mode='w+',order='C',dtype=np.float64,shape=(1,5))
#func -> some method, like i.e. sin()
#in numexpr it will be simple
ne.evaluate('sum(func(b*a+c),axis=1)')
#in numpy with einsum it will have to be with creating additional out-of-dot handling array
d=np.require(np.memmap('d.npy',mode='w+',order='C',dtype=np.float64,shape=(10,5)),requirements=['O'])
np.einsum('ij,kj->ki',b,a,out=d)
d+=c
func(d,out=d)
np.einsum('ij->i',d,out=c)
使用没有 RAM 的 CPU 是否有可能比 numexpr 更快? Cython + FORTRAN lapack 或 blass 怎么样?欢迎任何提示或技巧!谢谢你的帮助!
编辑信息:顺便说一句,我使用的笔记本电脑配备 Intel Core2Duo t9300 CPU、2.7 GB RAM(由于一些 BIOS 问题,只能从 4GB 看到)、SSD 250GB、旧的 Intel GPU。由于 RAM 水平较低(主要由 Firefox 和一些插件使用),因此没有太多空间用于编码,因此这就是我避免使用它的原因 xD。
我觉得我在编程方面处于高级水平(步骤 1/1000),但现在我不知道代码如何在硬件上工作 - 我只是猜测(所以我的想法可能会出现一些错误 xD)。
EDIT:我在 cython 中编写了一些代码,用于使用 numexpr 和 cython prange for 循环计算正弦波。
脉动数据(om、eps、Spectra、Amplitude)存储在 OM numpy.memmap 中,时间数据(t、z)存储在 TI numpy.memmap 中。 OM 的形状类似于 (4,1,2500),TI 的形状类似于 (2,1,5e+5,1) - 我只需要它的形状。
cdef inline void sine_wave_numexpr(OM,TI,int num_of_threads):
cdef long m,n=10
cdef Py_ssize_t s=TI.shape[2]/n
cdef str ex_sine_wave=r'sum(A*sin(om*ti+eps),axis=1)'
cdef dict dct={'A':OM[3],'om':OM[0],'eps':OM[2]}
for m in range(n):
sl=slice(s*m,s*(m+1))
dct['ti']=TI[0,0,sl]
evaluate(ex_sine_wave,
global_dict=dct,
out=TI[1,0,sl,0])
cdef inline void sine_wave_cython(double[:,:,::1]OM,double[:,:,:,::1]TI,int num_of_threads):
cdef int i,j
cdef Py_ssize_t n,m
cdef double t,A,om,eps
n=OM.shape[2]
m=TI.shape[2]
for i in prange(m,nogil=True,num_threads=num_of_threads):
t=TI[0,0,i,0]
for j in prange(n,num_threads=num_of_threads):
A=OM[3,0,j]
om=OM[0,0,j]
eps=OM[2,0,j]
TI[1,0,i,0]+=A*sin(om*t+eps)
cpdef inline void wave_elevation(double dom,OM,TI,int num_of_threads, str method='cython'):
cdef int ni
cdef double i,j
cdef Py_ssize_t shape=OM.shape[2]
numexpr_threads(num_of_threads)
OM[2,0]=2.*np.random.standard_normal(shape)
evaluate('sqrt(dom*2*S)',out=OM[3],
local_dict={'dom':dom,'S':OM[1]})
if method=='cython':
sine_wave_cython(OM,TI,num_of_threads)
elif method=='numexpr':
sine_wave_numexpr(OM,TI,num_of_threads)
TI.shape=TI.shape[:3]
我刚刚开始使用 Cython,所以它可能没有得到很好的优化。就目前而言,使用 prange 的代码与使用 numexpr 的代码花费的时间相同(包括这部分在内的所有代码的 RAM 使用量为 100 MB,CPU 为 50%,SSD 较低 - 计算时间为 1-2 分钟)。我尝试使用内存视图,但随着时间的推移,这创建了一些本地副本并使用了 RAM。我需要达到高级步骤 3/1000 才能了解如何使用内存视图。