gpt4 book ai didi

python - Cython 生成的 C++ 代码中可能存在错误

转载 作者:太空狗 更新时间:2023-10-29 23:13:38 26 4
gpt4 key购买 nike

我正在尝试为 __gnu_parallel::sort 创建一个 Cython 包装器,就像他们在这个线程中所做的一样 Parallel in-place sort for numpy arrays .

这是我对 wrapparallel.pyx 的简化代码:

import cython
cimport cython

cdef extern from "<parallel/algorithm>" namespace "__gnu_parallel":
cdef void sort[T](T first, T last) nogil

def parallel_sort(double[::1] a):
sort(&a[0], &a[a.shape[0] - 1])

我生成 C++ 代码:

cython --cplus wrapparallel.pyx

编译和链接:

g++ -g -march=native -Ofast -fpic -c wrapparallel.cpp -o wrapparallel.o -fopenmp -I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7
g++ -g -march=native -Ofast -shared -o wrapparallel.so wrapparallel.o -lpthread -ldl -lutil -lm -lpython2.7 -lgomp

现在测试一下:

In [1]: import numpy as np
from wrapparallel import parallel_sort

a = np.random.randn(10)
parallel_sort(a)
a

Out[1]: array([-1.23569683, -1.05639448, -0.76990205, -0.2512839 , -0.25022328,
0.12711458, 0.81659571, 0.92205287, 2.15019125, -0.45902146])

正如在原始线程的评论中指出的那样,此代码不会对最后一个元素进行排序,并且评论员建议在调用 pyx 文件中的排序时删除“-1”。然而,此更改不会解决任何问题,因为 a[a.shape[0]] 将超出范围。

这让我怀疑 C++ 代码中可能存在问题。实际调用 __gnu_parallel::sort 的代码片段如下所示:

static PyObject *__pyx_pf_12wrapparallel_parallel_sort(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_a) {
PyObject *__pyx_r = NULL;
__Pyx_RefNannyDeclarations
Py_ssize_t __pyx_t_1;
int __pyx_t_2;
Py_ssize_t __pyx_t_3;
int __pyx_lineno = 0;
const char *__pyx_filename = NULL;
int __pyx_clineno = 0;
__Pyx_RefNannySetupContext("parallel_sort", 0);

__pyx_t_1 = 0;
__pyx_t_2 = -1;
if (__pyx_t_1 < 0) {
__pyx_t_1 += __pyx_v_a.shape[0];
if (unlikely(__pyx_t_1 < 0)) __pyx_t_2 = 0;
} else if (unlikely(__pyx_t_1 >= __pyx_v_a.shape[0])) __pyx_t_2 = 0;
if (unlikely(__pyx_t_2 != -1)) {
__Pyx_RaiseBufferIndexError(__pyx_t_2);
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
__pyx_t_3 = ((__pyx_v_a.shape[0]) - 1);
__pyx_t_2 = -1;
if (__pyx_t_3 < 0) {
__pyx_t_3 += __pyx_v_a.shape[0];
if (unlikely(__pyx_t_3 < 0)) __pyx_t_2 = 0;
} else if (unlikely(__pyx_t_3 >= __pyx_v_a.shape[0])) __pyx_t_2 = 0;
if (unlikely(__pyx_t_2 != -1)) {
__Pyx_RaiseBufferIndexError(__pyx_t_2);
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
}
__gnu_parallel::sort<double *>((&(*((double *) ( /* dim=0 */ ((char *) (((double *) __pyx_v_a.data) + __pyx_t_1)) )))), (&(*((double *) ( /* dim=0 */ ((char *) (((double *) __pyx_v_a.data) + __pyx_t_3)) )))));


/* function exit code */
__pyx_r = Py_None; __Pyx_INCREF(Py_None);
goto __pyx_L0;
__pyx_L1_error:;
__Pyx_AddTraceback("wrapparallel.parallel_sort", __pyx_clineno, __pyx_lineno, __pyx_filename);
__pyx_r = NULL;
__pyx_L0:;
__PYX_XDEC_MEMVIEW(&__pyx_v_a, 1);
__Pyx_XGIVEREF(__pyx_r);
__Pyx_RefNannyFinishContext();
return __pyx_r;
}

我的 C++ 知识不足以掌握这里发生的事情,所以我的问题是:调用 __gnu_parallel::sort 有什么问题吗?我该如何更改它以将最后一个元素也包含在内存 View 中?

编辑:

sort(&a[0], &a[a.shape[0] - 1]) 更改为 sort(&a[0], &a[a.shape[ 0]]) 是正确的。但是,这会引发 IndexError: Out of bounds on buffer access (axis 0)
除非指示 cython 编译器使用 boundscheck = False 指令。为了完整起见,wrapparallel.pyx 文件应如下所示:

# cython: boundscheck = False
import cython
cimport cython

cdef extern from "<parallel/algorithm>" namespace "__gnu_parallel":
cdef void sort[T](T first, T last) nogil

def parallel_sort(double[::1] a):
sort(&a[0], &a[a.shape[0]])

最佳答案

谁告诉你删除 -1是正确的。排序函数需要类似于 range 的参数(例如 range(0, 3) <-> [0, 1, 2])

因此您需要为排序算法提供第一个不在您希望排序的数组中的指针。给定以下数据:

addr | 0x00 | 0x01 | 0x02 | 0x03 |
-----+------+------+------+------+
elem | 3.12 | 5.89 | 0.56 | - |

你会调用 sort(addr, &addr[3]) .

您可以想象排序函数以如下方式迭代数组中的项目:

void func(double *start, double *end) {
for (double *current = start; current != end; current += 1) {
double value = *current;
// do something
}
}

请注意 endcurrent 时循环停止,指针将永远不会被取消引用(访问)指针等于 end .

当你写 &a[a.shape[0]] ,编译器足够聪明,可以判断出您只是在尝试进行指针运算,而实际上不会取消对无效指针的引用。

关于python - Cython 生成的 C++ 代码中可能存在错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37931814/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com