Cython用等价的

时间:2017-08-23 09:46:04

标签: c++ list cython

我正在尝试使用两个大小的双元组列表作为输入和输出来加速Cython中已经非常优化的函数。要做到这一点,我需要首先在纯C中使用它。

在python中以某种方式c​​ython化了元组语法 ressembles 这个:

def f(inputList1, inputList2):
    cdef double p, i10,i11,i20,i21,a0,a1

    a0,a1=inputList1[-1]
    for i10,i11 in inputList1:
      outputList=[]
      #some more computations involving a0 and a1 
      for i20,i21 in inputList2:
        p=f(i10,i11,a0,a1,i21,i20)  #f returns a double
        if p==0:
          outputList.append((i10,i21))
        else if p>0:
          outputList.append(g(i10,i21,i20,i21)) #g returns two outputs that are parsed as a two sized tuples automatically
       if len(outputList)<1:
         return []
       #some more computations
       a0, a1=i10, i11
  return outputList

细节与速度和语法的重要性无关:它在for循环中使用元组解包来打破元组,并且可以使用append()附加整个元组,它也可以获取最后一个元素列表,它可以返回一个空列表。它还可以将g的两个输出转换为元组。

我正在尝试将所有的python改为纯C来提高速度或至少不会损害速度在我的脑海中它应该是可行的(也许我错了?)。因此,当g必须变为纯C时,必须返回一个对象(我猜多个输出是不可能的?)

我的第一个想法是使用std::vectorsstd::pairs列表列表成为vector[pair[double,double]]我修改了g以返回pair[double,double]而不是两个双打

cdef vector[pair[double,double]] f(vector[pair[double,double]] inputList1, vector[pair[double,double]] inputList2):
    cdef double p, i10,i11,i20,i21,a0,a1
    #I have to add the pairs as I cannot use the for a,b in syntax
    cdef pair[double,double] i1,i2,e
    cdef vector[pair[double,double]] outputList, emptyList
    a0,a1=inputList.back()
    for i1 in inputList1:
      i10=i1.first
      i11=i1.second
      outputList=emptyList
      #some more computations involving a0 and a1 

      for i2 in inputList2:
        i20=i2.first
        i21=i2.second
        p=f(i10,i11,a0,a1,i21,i20) #f returns a double
        if p==0.:
          outputList.push_back(i1) #I am now using push_back and not append
        else if p>0.:
          outputList.push_back(g(i10,i21,i20,i21)) #g now returns a pair
       if outputList.size()<1:
         return outputList
       #some more computations
       a0, a1=i10, i11
  return outputList

一切都是纯粹的C但是慢3倍 !!! 我也尝试了std::listlist[list[double]]我的速度也减少了3倍!我使用i1.back()i1.front()而不是第一和第二我想这也让我速度快。这是什么原因?是否有更好的C对象可供使用?是我正在使用的语法?明确地做i20=i2.first等等是什么让它变得如此缓慢?

特别是g的语法现在看起来真的很愚蠢,也许瓶颈来自那里:

cdef pair[double,double] g(double a, double b, double c, double d):
  #looks ugly that I have to define res
  cdef pair[double,double] res
  cdef double res_int
  res_1=computations1(a,b,c,d)
  res_2=computations2(a,b,c,d)
  #looks ugly
  res.first=res_1
  res.second=res_2
  return res

而不是像以前一样简单地返回res_1,res_2:

编辑:我重新编写了所有内容以对不同的解决方案进行基准测试:

-it结果列表[list [double]]对我来说不是一个选项,因为稍后在我的代码中我需要通过索引访问列表的特定元素

-vector [np.ndarray [DTYPE,ndim = 1]]不起作用我想你不能用Python对象形成一个向量

-vector [pair [double,double]]实际上确实比Python列表版本更快!

对于100000次迭代,Python版本总共

Python

1.10413002968s

0.781275987625s (vector [pair [double,double]]) C 版本。

它仍然看起来非常难看,我仍然想听听这是否是正确的方法

0 个答案:

没有答案