1

独自の 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を参照)。

4

0 に答える 0