2011-09-16 47 views
3

私はcythonでいくつかのpythonコードをスピードアップしようとしています。私は、cythonの-aオプションを使用して、どこで改善できるかを見ています。私の理解は、生成されたHTMLファイルでは、ハイライトされた行は、Python関数が呼び出される行です - それは正しいですか?Cython numpy配列インデックス

以下の簡単な関数では、バッファ構文を使用してnumpy配列の引数arrを宣言しました。私はこれにより、インデックス作成操作をPython関数を呼び出すことなくCで行うことができると考えました。しかし、cython -a(バージョン0.15)は、要素の値を設定する行を強調表示していますが、要素の1つを読み取った部分ではありませんが、arrの値が設定されています。なぜこれが起こるのですか? numpyの配列要素にアクセスするより効率的な方法はありますか?

import numpy 
cimport numpy 

def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i]   #not highlighted 
     arr[i] = 1.0 + elem #highlighted 

EDIT:また、どのようにmodeバッファ引数はnumpyのと対話していますか? order引数がnumpy.arrayに変更されていないと仮定すると、いつもmode='c'を使用しても安全ですか?これは実際にパフォーマンスに影響を及ぼしますか?

delnanのコメント後に編集:arr[i] += 1も強調表示されています(そのため、最初に分割して問題の原因となっている部分を確認しています)。私は(これは強調表示する内容に違いはありません)物事を単純化するために境界チェックをオフにした場合、生成されたCコードは次のとおりです。

/* "ct.pyx":11 
* cdef int i 
* cdef double elem 
* for i in xrange(10):    # <<<<<<<<<<<<<< 
*  elem = arr[i] 
*  arr[i] = 1.0 + elem 
*/ 
    for (__pyx_t_1 = 0; __pyx_t_1 < 10; __pyx_t_1+=1) { 
    __pyx_v_i = __pyx_t_1; 

    /* "ct.pyx":12 
* cdef double elem 
* for i in xrange(10): 
*  elem = arr[i]    # <<<<<<<<<<<<<< 
*  arr[i] = 1.0 + elem 
*/ 
    __pyx_t_2 = __pyx_v_i; 
    __pyx_v_elem = (*__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_2, __pyx_bstride_0_arr)); 

    /* "ct.pyx":13 
* for i in xrange(10): 
*  elem = arr[i] 
*  arr[i] = 1.0 + elem    # <<<<<<<<<<<<<< 
*/ 
    __pyx_t_3 = __pyx_v_i; 
    *__Pyx_BufPtrStrided1d(double *, __pyx_bstruct_arr.buf, __pyx_t_3, __pyx_bstride_0_arr) = (1.0 + __pyx_v_elem); 
    } 
+0

は '[i]が+ = 1 '強調しARRですか?また、 'cython -a'によって生成されたHTML文書の中で、その特定の行のために生成されたコードを見ることができます。おそらく、Python API呼び出しがその行でどのように起こるかを知るのに役立ちます。 – delnan

答えて

4

答えは蛍光ペンは、読者を愚か者ということです。 あなたのコードをコンパイルしました。ハイライトの下で生成された命令は、エラーケースと戻り値を処理するために必要なものです(配列割り当てには関係ありません)。

確かにあなたが読むためにコードを変更した場合:

def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i] 
     arr[i] = 1.0 + elem 
    return # + add this 

ハイライトは最後の行になると割り当てではない以上でしょう。

あなたはさらに、@のcython.boundscheckを使用してコードをスピードアップすることができます。

import numpy 
cimport numpy 
cimport cython 

@cython.boundscheck(False) 
def foo(numpy.ndarray[double, ndim=1] arr not None): 
    cdef int i 
    cdef double elem 
    for i in xrange(10): 
     elem = arr[i] 
     arr[i] = 1.0 + elem 
    return 
+0

提供されているCコードでは、バインドされたチェックはなく、インデックスの折り返しはありません。だから私は質問者が彼のsetup.pyでそれらを無効にしたと仮定します。 – rocksportrocker

関連する問題