それで、私が持っているpythonコンポーネントのC拡張を作成することを検討しています。次に、OMP を使用して、最終的に Python+C の組み合わせソリューションを実行するマシンからできる限り多くの利点を活用することを考えました。
誰かが似たようなことを試したことがありますか?そのような解決策を失敗させる可能性のある特定の不都合な詳細はありますか?
前もって感謝します!
それで、私が持っているpythonコンポーネントのC拡張を作成することを検討しています。次に、OMP を使用して、最終的に Python+C の組み合わせソリューションを実行するマシンからできる限り多くの利点を活用することを考えました。
誰かが似たようなことを試したことがありますか?そのような解決策を失敗させる可能性のある特定の不都合な詳細はありますか?
前もって感謝します!
私は、電波天文学における大規模なデータ マイニング タスクでこれを成功させました。例については、 https://github.com/ewanbarr/sigpyproc.gitを参照してください。
注意すべきことは、これらのケースで構築した C ライブラリは、ネイティブの Python 拡張としてではなく、ctypes を介してアクセスされるということです。
たとえば、次のようになります。
パイソン: test.py
import ctypes as C
import numpy as np
from numpy.ctypeslib import as_ctypes
lib = C.CDLL("libmytest.so")
def set_N_threads(nthreads):
self.lib.omp_set_num_threads(nthreads)
def do_some_task(input_array):
input_array = input_array.astype("float32")
output_array = np.empty_like(input_array)
lib.do_some_omp_task(as_ctypes(input_array),
as_ctypes(output_array),
C.c_size_t(input_array.size))
return output_array
C: test.c
#include <omp.h>
void do_some_omp_task(float* input_array,
float* output_array,
size_t size)
{
int ii;
#pragma omp parallel for default(shared) private(ii)
for (ii=0;ii<size;ii++)
do something using ii and the arrays
}
コンパイル:
gcc -O3 -lm -fopenmp -fPIC -c test.c -o test.o
gcc -shared -lgomp -o libmytest.so test.o
あなたの質問に答えるために、私はこの種のセットアップに問題はなく、達成可能な速度の改善は印象的でした (ただし、上記の例は OMP の恩恵を受けません)。
Cythonにはparallel.prange()
、例があります。
PyEval_InitThreads
手動で行うには、拡張モジュールの初期化を呼び出します。Python 以外のスレッドを fork する際に GIL を解放します。たとえば、OMP 並列セクションを .xml でラップしPy_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS
ます。を使用して Python オブジェクトにアクセスする必要がある場合は、GIL を取得/解放しますstate = PyGILState_Ensure()/PyGILState_Release(state)
。以下に例を示します(シャットダウン時にモジュールのスレッド化でエラーが発生するように複雑になっています)。問題を回避するthreading
には、モジュールの初期化時にインポートします。