簡體   English   中英

用於改進cython代碼的高效矩陣向量結構

[英]Efficient matrix vector structure for improving cython code

我必須在 SODE 系統上運行一些模擬。 由於我需要使用隨機圖,我認為最好使用 python 生成圖形的相鄰矩陣,然后使用 C 生成模擬。 所以我轉向了cython。

我按照cython 文檔的提示編寫了代碼,以盡可能提高其速度。 但是知道我真的不知道我的代碼是否好。 我也運行cython toast.pyx -a ,但我不明白這些問題。

  • 在 cython 中用於向量和矩陣的最佳結構是什么? 我應該如何界定,例如, bruit在我的代碼以np.arraydouble 請注意,我將比較矩陣的元素(0 或 1)以便求和。 結果將是一個矩陣 NxT,其中 N 是系統的維度,T 是我想用於模擬的時間。
  • 我在哪里可以找到double[:]的文檔?
  • 如何在函數的輸入中聲明向量和矩陣(下面的 G、W 和 X)? 我怎樣才能用double聲明一個向量?

但我讓我的代碼為我說話:

from __future__ import division
import scipy.stats as stat
import numpy as np
import networkx as net

#C part
from libc.math cimport sin
from libc.math cimport sqrt

#cimport cython
cimport numpy as np
cimport cython
cdef double tau = 2*np.pi  #http://tauday.com/

#graph
def graph(int N, double p):
    """
    It generates an adjacency matrix for a Erdos-Renyi graph G{N,p} (by default not directed).
    Note that this is an O(n^2) algorithm and it gives an array, not a (sparse) matrix.
    
    Remark: fast_gnp_random_graph(n, p, seed=None, directed=False) is O(n+m), where m is the expected number of edges m=p*n*(n-1)/2.
    Arguments:
        N : number of edges
        p : probability for edge creation
    """
    G=net.gnp_random_graph(N, p, seed=None, directed=False)
    G=net.adjacency_matrix(G, nodelist=None, weight='weight')
    G=G.toarray()
    return G


@cython.boundscheck(False)
@cython.wraparound(False)
#simulations
def simul(int N, double H, G, np.ndarray W, np.ndarray X, double d, double eps, double T, double dt, int kt_max):
    """
    For details view the general description of the package.
    Argumets:
        N : population size
        H : coupling strenght complete case
        G : adjiacenty matrix
        W : disorder
        X : initial condition
        d : diffusion term
        eps : 0 for the reversibily case, 1 for the non-rev case
        T : time of the simulation
        dt : increment time steps
        kt_max = (int) T/dt
    """
    cdef int kt
    #kt_max =  T/dt to check
    cdef np.ndarray xt = np.zeros([N,kt_max], dtype=np.float64)
    cdef double S1 = 0.0
    cdef double Stilde1 = 0.0
    cdef double xtmp, xtilde, x_diff, xi
    
    cdef np.ndarray bruit = d*sqrt(dt)*stat.norm.rvs(N)
    cdef int i, j, k

    for i in range(N): #setting initial conditions
        xt[i][0]=X[i]
        
    for kt in range(kt_max-1):
        for i in range(N):
            S1 = 0.0
            Stilde1= 0.0
            xi = xt[i][kt]
        
            for j in range(N): #computation of the sum with the adjiacenty matrix
                if G[i][j]==1:
                    x_diff = xt[j][kt] - xi
                    S2 = S2 + sin(x_diff)

            xtilde = xi + (eps*(W[i]) + (H/N)*S1)*dt + bruit[i]

            for j in range(N):
                if G[i][j]==1:
                    x_diff = xt[j][kt] - xtilde
                    Stilde2 = Stilde2 + sin(x_diff)
        
            #computation of xt[i]
            xtmp = xi + (eps*(W[i]) + (H/N)*(S1+Stilde1)*0.5)*dt + bruit
            xt[i][kt+1] = xtmp%tau

    return xt

非常感謝!

更新

我將變量定義的順序np.arraydouble ,將xt[i][j]更改為xt[i,j]並將矩陣更改為long long 代碼現在更快了,html 文件上的黃色部分就在聲明的周圍。 謝謝!

from __future__ import division
import scipy.stats as stat
import numpy as np
import networkx as net

#C part
from libc.math cimport sin
from libc.math cimport sqrt

#cimport cython
cimport numpy as np
cimport cython
cdef double tau = 2*np.pi  #http://tauday.com/

#graph
def graph(int N, double p):
    """
    It generates an adjacency matrix for a Erdos-Renyi graph G{N,p} (by default not directed).
    Note that this is an O(n^2) algorithm and it gives an array, not a (sparse) matrix.

    Remark: fast_gnp_random_graph(n, p, seed=None, directed=False) is O(n+m), where m is the expected number of edges m=p*n*(n-1)/2.
    Arguments:
        N : number of edges
        p : probability for edge creation
    """
    G=net.gnp_random_graph(N, p, seed=None, directed=False)
    G=net.adjacency_matrix(G, nodelist=None, weight='weight')
    G=G.toarray()
    return G


@cython.boundscheck(False)
@cython.wraparound(False)
#simulations
def simul(int N, double H, long long [:, ::1] G, double[:] W, double[:] X, double d, double eps, double T, double dt, int kt_max):
    """
    For details view the general description of the package.
    Argumets:
        N : population size
        H : coupling strenght complete case
        G : adjiacenty matrix
        W : disorder
        X : initial condition
        d : diffusion term
        eps : 0 for the reversibily case, 1 for the non-rev case
        T : time of the simulation
        dt : increment time steps
        kt_max = (int) T/dt
    """
    cdef int kt
    #kt_max =  T/dt to check
    cdef double S1 = 0.0
    cdef double Stilde1 = 0.0
    cdef double xtmp, xtilde, x_diff

    cdef double[:] bruit = d*sqrt(dt)*np.random.standard_normal(N)

    cdef double[:, ::1] xt = np.zeros((N, kt_max), dtype=np.float64)
    cdef double[:, ::1] yt = np.zeros((N, kt_max), dtype=np.float64)
    cdef int i, j, k

    for i in range(N): #setting initial conditions
        xt[i,0]=X[i]

    for kt in range(kt_max-1):
        for i in range(N):
            S1 = 0.0
            Stilde1= 0.0

            for j in range(N): #computation of the sum with the adjiacenty matrix
                if G[i,j]==1:
                    x_diff = xt[j,kt] - xt[i,kt]
                    S1 = S1 + sin(x_diff)

            xtilde = xt[i,kt] + (eps*(W[i]) + (H/N)*S1)*dt + bruit[i]

            for j in range(N):
                if G[i,j]==1:
                    x_diff = xt[j,kt] - xtilde
                    Stilde1 = Stilde1 + sin(x_diff)

            #computation of xt[i]
            xtmp = xt[i,kt] + (eps*(W[i]) + (H/N)*(S1+Stilde1)*0.5)*dt + bruit[i]
            xt[i,kt+1] = xtmp%tau

    return xt

cython -a顏色編碼 cython 源。 如果您單擊一行,它會顯示相應的 C 源代碼。 根據經驗,您不希望內部循環中出現任何黃色內容。

在您的代碼中跳出幾件事:

  • x[j][i]在每次調用時為x[j] x[j][i]創建一個臨時數組,因此請改用x[j, i]
  • 而不是cdef ndarray x更好地提供維度和cdef ndarray[ndim=2, dtype=float]cdef ndarray[ndim=2, dtype=float] )或 --- 最好 --- 使用類型化的 memoryview 語法: cdef double[:, :] x

例如,而不是

cdef np.ndarray xt = np.zeros([N,kt_max], dtype=np.float64)

更好地使用

cdef double[:, ::1] xt = np.zeros((N, kt_max), dtype=np.float64)
  • 確保您以緩存友好模式訪問內存。 例如,確保您的數組按 C 順序排列(最后一個維度變化最快),將內存視圖聲明為double[:, ::1]並迭代數組,最后一個索引變化最快。

編輯:請參閱http://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html了解類型化 memoryview語法double[:, ::1]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM