2

こんにちは、高速な行列の乗算、加算、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を搭載したラップトップで作業しています。いくつかのアドオンを含む Firefox で主に使用される RAM のレベルが低いため、コーディング用のスペースがあまり残っていないため、xD の使用を避けています。

そして、私はプログラミングの上級レベル (ステップ 1/1000) にいるように感じますが、今のところコードがハードウェア上でどのように機能するかはわかりません - 私はそれを推測しているだけです (したがって、私の考えのいくつかの間違いは xD に見えるかもしれません)。

編集: numexpr と cython prange for-loop を使用して正弦波を計算するコードを cython で作成しました。

脈動データ (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 分です)。私はmemoryviewsを試しましたが、それはいくつかのローカルコピーを作成し、時間の経過とともにRAMを使用しました。メモリビューの操作方法を理解するには、上級レベルのステップ 3/1000 である必要があります。

4

0 に答える 0