おそらく誤解があります。この関数はc配列を返しませんが、メモリビュースライスを返します。あなたは私を信じる必要はありません。nogil
を削除してcythonを呼び出して確認できます。作成したの* .cファイルでは、__Pyx_memviewslice
が重要な一部である、あなたの関数のC-署名を確認することができます。
static CYTHON_INLINE __Pyx_memviewslice __pyx_f_4file_array_test(CYTHON_UNUSED double *__pyx_v_x)
このメモリビューは、Pythonのオブジェクトなので、それはガベージコレクタに登録する必要があり、したがって、グローバルインタープリタロックが必要です。つまり、「Gilなしで操作できません」というエラーメッセージが表示されます。
ですから、少なくとも3つのオプションがあります。
- は、「nogil」でそれを行うことは本当にそれほど重要なのですか?もしそうでなければ、それをドロップしてください。最も簡単な解決策、欠点です。パフォーマンスが低下する可能性があります。
- 実際のC配列、つまり
int *res = (int *) malloc(2*sizeof(int))
を使用します。高速ですが、欠点です。自分でメモリを管理する必要があります。
- C++と
std::vector<int>
を使用すると、メモリを管理する必要はありませんが、C++に切り替える必要があるという利点があります。
可能性1.の改善が(これは実際のコードは、この例かもしれませんがための大きな違いをすることはありません)だけでそれが必要とされる最後の行、ためにギルをAQUIREすることです:
cdef inline int[:] array_test(double *x) nogil:
cdef int output[2]
output[0]=1
output[1]=9
with gil:
return output
OPが提案されているように、更なる可能性はに機能の署名を変更することであろう。
ここのトリック:fuction array_test
は結果としてメモリビュースライスを作成せず、ガベージコレクタに登録する必要もなく、 "nogil"が可能です。
array_test
の呼び出しがより煩雑になり、呼び出し側がoutput
メモリビューを作成するためにgilを持たなければならないというようなマイナーなマイナス面があります。しかし、呼び出し側は結果を格納するデータ構造の種類(numpy配列か多分何か)を判断できるという利点もあります。
出典
2017-10-11 19:56:52
ead
ありがとうございました!問題を回避する別の方法は、関数を無効にして、空の入力配列を変更することです。 – user3433489
@ user3433489どのように単純です!これについて考えなかった... – ead