9

私はこの種のコードをコンパイルしようとしています:

def my_func(double c, int m):
    cdef double f[m][m]

    f = [[c for x in range(m)] for y in range(m)]
    ...

これは発生します:

Error compiling Cython file:
------------------------------------------------------------
def grow(double alpha, double beta, double gamma, int m, int s):
    cdef double f[m][m]
                     ^
------------------------------------------------------------
test.pyx:6:22: Not allowed in a constant expression

その後、指摘された場所で変数を使用できないと想定し、数値で試します:

def my_func(double c, int m):
    cdef double f[500][500]

    f = [[c for x in range(500)] for y in range(500)]
    ...

しかし、私は得る:

Error compiling Cython file:
------------------------------------------------------------
    f = [[beta for x in range(500)] for y in range(500)]
     ^
------------------------------------------------------------
test.pyx:13:6: Assignment to non-lvalue 'f'

そこで、cython コードで 2D リストを宣言して作成する方法を考えています。「cython 2D list」のグーグルのドキュメントでこの種の例を見つけることができませんでした

4

2 に答える 2

9

Cythonではリスト内包表記を使用しないでください。通常のPythonリストを作成するため、スピードアップはありません。Wikiによると、Cythonでは次のように動的割り当てを使用する必要があります。

from libc.stdlib cimport malloc, free

def my_func(double c, int m):
    cdef int x
    cdef int y
    cdef double *my_array = <double *>malloc(m * m * sizeof(double))

    try:

        for y in range(m):
            for x in range(m):
                #Row major array access
                my_array[ x + y * m ] = c

        #do some thing with my_array

    finally:
       free( my_array )

ただし、2D配列のPythonオブジェクトが必要な場合は、NumPyを使用することをお勧めします。

于 2013-01-02T09:54:35.400 に答える
7
cdef double f[500][500]

これは、500個のdoubleの500個のC配列のC配列を宣言しています。これは、間接参照なしで500 * 500パックされたdouble値(この場合、Cythonがファンキーなことをしない限り、スタックに格納されます)であり、パフォーマンスとキャッシュ使用率を向上させますが、明らかに厳しい制限を追加します。たぶんあなたはこれが欲しいでしょう、しかしあなたはそれが最初に何を意味するかを知るのに十分なCを学ぶべきです。ちなみに、1つの制限は、サイズがコンパイル時定数でなければならないことです(Cバージョンによって異なります。C99およびC10では許可されています)。これが最初のエラーメッセージです。

配列を使用する場合fは、意味がないため、以前のように初期化することはありません。fはすでに500x500の二重変数であり、配列全体を割り当てることはできません(これは、後者のエラーメッセージが通知しようとしていることです)。float特に、リスト内包表記は、本格的な「ボックス化された」Pythonオブジェクト(この場合はオブジェクト)を含む本格的なPythonリストオブジェクト(Cythonからも使用できます。以下を参照)を作成します。リストはC配列と互換性がありません。初期化には、アイテムの割り当てを含むネストされたforループを使用します。最後に、このようなアレイは500 * 500 * 8バイトを使用します。これは、ほぼ2MiBです。一部のシステムでは、これはスタック全体よりも大きく、他のすべてのシステムでは、スタックの非常に大きな部分であるため、お勧めできません。

Pythonリストを使用する場合は、パフォーマンスとメモリ使用量がそれほど改善されないことに注意してください(コードがほとんどそのリストを操作していると仮定します)が、見返りにある程度の利便性を取り戻すことができます。を省略したり、タイプとしてcdef使用したりすることもできます(これも機能するはずですが、何も得られないため、省略した方がよいでしょう)。listobject

NumPy配列は、より高速で、メモリ効率が高く、使い勝手が良い場合があります。NumPyの操作に関してアルゴリズムのパフォーマンスが重要な部分を実装できる場合は、Cythonをまったく使用せずに目的のスピードアップを得ることができます。

于 2013-01-02T09:54:32.123 に答える