Cython生成的C ++代码

时间:2016-06-20 21:06:14

标签: python c++ cython

我试图为__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])

正如原始帖子中的评论所指出的,这段代码没有对最后一个元素进行排序,而评论员则建议&#34; - 1&#34;在调用中删除pyx文件中的排序。然而,由于[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有什么问题吗?我怎样才能改变它以包含memoryview中的最后一个元素?

编辑:

sort(&a[0], &a[a.shape[0] - 1])更改为sort(&a[0], &a[a.shape[0]])的答案是正确的。但是,除非指示cython编译器使用IndexError: Out of bounds on buffer access (axis 0) 指令,否则这将引发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 个答案:

答案 0 :(得分:0)

告诉您删除connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 的人是对的。 sort函数需要类似于-1的参数(例如range

因此,您需要为排序算法提供第一个指针,该指针不在您要排序的数组中。鉴于以下数据:

range(0, 3) <-> [0, 1, 2]

您可以致电addr | 0x00 | 0x01 | 0x02 | 0x03 | -----+------+------+------+------+ elem | 3.12 | 5.89 | 0.56 | - |

您可以想象sort函数以类似这样的方式迭代数组中的项:

sort(addr, &addr[3])

请注意,void func(double *start, double *end) { for (double *current = start; current != end; current += 1) { double value = *current; // do something } } 指针永远不会被取消引用(访问),因为当end指针等于current时循环停止。

当你编写end时,编译器足够聪明,可以发现你只是想做指针算术,并且实际上不会取消引用无效的指针。

相关问题