独自の OpenMP C++ 拡張によって返される変数にアクセスしようとすると、Python インタープリターでセグメンテーション違反が発生します。
私が見つけたすべての解決策は、ctypesまたはcython(使用できません)のいずれかを使用しています。http://snatverk.blogspot.de/2012/03/c-parallel-modules-for-python.htmlは、OpenMP 対応の Python 拡張機能の小さな例を示しています。例のように for ループを実装しようとしましたが、まだ機能しません。
My Code 拡張コード関数は次のようになります。
static PyObject *
matcher_match(PyObject *self, PyObject *args)
{
if(PyTuple_Size(args) != 2)
{
return NULL;
}
PyObject *names = PyTuple_GetItem(args, 0);
Py_ssize_t namesSize = PyList_Size(names);
PyObject *namesB = PyTuple_GetItem(args, 1);
Py_ssize_t namesBSize = PyList_Size(namesB);
PyObject *matchIdcs = PyList_New(namesSize);
Py_BEGIN_ALLOW_THREADS;
int i, j;
#pragma omp parallel for private(i, j)
for(i = 0; i < namesSize; i++)
{
for(j = 0; j < namesBSize; j++)
{
// test_pair_ij is a pure C function without callbacks into python
// it only uses the C++ STL like std::vector
float a = PyFloat_AsDouble(PyList_GetItem(names, i));
float b = PyFloat_AsDouble(PyList_GetItem(namesB, j));
bool res = test_pair_ij(a, b)
PyObject *matchVal;
if(res)
{
matchVal = Py_BuildValue("i", j);
}
else
{
matchVal = Py_BuildValue("i", -1);
}
PyList_SetItem(matchIdcs, i, matchVal);
}
}
Py_END_ALLOW_THREADS;
return matchIdcs;
}
関数 matcher_match() は、names と namesB の 2 つのリストを受け取ります。関数 test_pair_ij() によって示される特定の条件について、names と namesB (それらの float 属性) のすべての組み合わせをチェックします。この関数は、Python にコールバックしない純粋な C(++) 実装です。
C 拡張機能は次のように呼び出されます。
from matcher import match
# some random lists for this example
names = ['123', '231', ...]
namesB = ['342', ...]
matchResult = match(names, namesB)
import pandas as pd
mr = pd.Series(matchResult)
mr.to_csv('matchResult.csv')
リスト名と名前 B がかなり小さい場合、コードは正常に実行されています。しかし、より大きなリストでは、Python コードで matchResult にアクセスできなくなりました。しようとすると、セグメンテーション違反が発生します(これはPythonインタープリターの内部にあると思います)。openmp を使用せずに C 拡張機能を再コンパイルしたところ、リストが大きくても問題なく動作しました。
問題は、拡張機能からアクセスする python 変数のメモリ内の混乱だと思います。これは GIL に関係している可能性がありますが、私はそれをリリースして取得しています。この場合、さらに変数をプライベートにする必要がありますか? これに関する他のアイデアはありますか?
EDIT : 関数 test_pair_ij の呼び出し引数を修正しました。
EDIT 2 : matchIdcs を保存するコードを修正
答え:
コードは GIL とPyList_SetItem(matchIdcs, i, matchVal);の呼び出しを解放していました。許可されていない python 構造を変更していました ( http://docs.cython.org/src/userguide/external_C_code.html#release-the-gilを参照)。