1

当我尝试访问由我自己的 OpenMP C++ 扩展返回的变量时,我在 python 解释器中遇到了分段违规。

我找到的所有解决方案都使用 ctypes 或 cython(我不能使用)。http://snatverk.blogspot.de/2012/03/c-parallel-modules-for-python.html展示了一个启用 OpenMP 的 python 扩展的小例子。尽管我尝试像示例中那样实现我的 for 循环,但它仍然不起作用。

我的代码扩展代码功能如下所示:

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。我检查名称和名称B(它们的浮点属性)的每个组合是否存在由函数test_pair_ij()指示的特定条件。该函数是一个纯 C(++) 实现,不会回调到 python。

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 有关,尽管我正在发布和获取它。在这种情况下,我是否需要将更多变量设为私有?对此还有其他想法吗?

编辑:修复函数 test_pair_ij 的调用参数。

编辑 2:存储 matchIdcs 的固定代码

答案

代码正在释放 GIL 并调用PyList_SetItem(matchIdcs, i, matchVal); 正在修改不允许的 python 结构(请参阅http://docs.cython.org/src/userguide/external_C_code.html#releasing-the-gil)。

4

0 回答 0