Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python cython:函数具有各种类型的参数_Python_Cython - Fatal编程技术网

Python cython:函数具有各种类型的参数

Python cython:函数具有各种类型的参数,python,cython,Python,Cython,我正在尝试将一个旧的Python代码修改为Cython以提高速度。类有一个init函数,允许各种类型的参数: class dRect: def __init__(self, *args): if len(args) == 1: # actual input is a list of four float numbers self.x0, self.y0, self.x1, self.y1 = args[0] elif len(arg

我正在尝试将一个旧的Python代码修改为Cython以提高速度。类有一个init函数,允许各种类型的参数:

class dRect:
    def __init__(self, *args):
        if len(args) == 1: # actual input is a list of four float numbers
            self.x0, self.y0, self.x1, self.y1 = args[0]
        elif len(args) == 4:  # actual input is four float numbers
            self.x0, self.y0, self.x1, self.y1 = args

# sample of initiating dRect instance
a = dRect([0, 1, 2, 3])
b = dRect(0, 1, 2, 3)
将其修改为Cython代码的正确方法是什么?或者我应该潜入这个世界的哪一部分?谢谢。

提速的大小(在任何情况下)取决于您可以做什么(在我的情况下,提速可达10倍)

  • 。cdefed类将比非cdef类快(请参见下面测试中的MyCyClass vs MyPyClass)
  • 在cdefed类的构造函数中,更喜欢传递Python浮点而不是传递Python整数。如果传入Python浮点而不是Python整数,则构造函数会更快。可能是因为将python float转换为double比将python integer转换为double更快
  • 在自由cdef函数中使用_unew__;()并避免元组初始化(如果可以避免的话)
  • 测试:

    这是我的时间安排

    正在运行类型为(输入)=float的非cdef类的use构造函数

    • 0.194803 0.199249 0.196051 0.2012200.265174μs(最慢)
    运行类型为(输入)=浮点的use构造函数(cdef)

    • 0.044000 0.048895 0.044641 0.045356 0.048148μs
    运行类型为(输入)=int的使用构造函数(cdef)

    • 0.090032 0.169924 0.089831 0.090147 0.091007μs
    使用double init运行usenew(cdef),输入为double

    • 0.026093 0.025533 0.029145 0.0236390.024517μs(最快)
    使用双初始化运行usenew(cdef),输入为int

    • 0.025040.024114 0.024084 0.025460 0.024183μs(最快,相当于上述速度)
    运行usenew(cdef)和tuple init

    • 0.042559 0.042985 0.042348 0.043527 0.043123μs

    您试图实现什么目标?您可以将python代码按原样进行cythonize。这段代码没有太大的加速潜力。
    
    cdef class MyCyClass:
        cdef public double x0
        cdef public double x1
        cdef public double x2
        cdef public double x3
        
        def __init__(self, *args):
            self.x0 = args[0]
            self.x1 = args[1]
            self.x2 = args[2]
            self.x3 = args[3]
        
    class MyPyClass:
        def __init__(self, *args):
            self.x0 = args[0]
            self.x1 = args[1]
            self.x2 = args[2]
            self.x3 = args[3]
    
    cdef new_MyCyClass_from_seq(args):
        my_obj = MyCyClass.__new__(MyCyClass)
        init_MyCyClass_from_seq(my_obj, args)
    
    cdef init_MyCyClass_from_seq(MyCyClass my_obj, args):
        my_obj.x0 = args[0]
        my_obj.x1 = args[1]
        my_obj.x2 = args[2]
        my_obj.x3 = args[3]
        
    cdef new_MyCyClass_from_double(double x0, double x1, double x2,  double x3):
        my_obj = MyCyClass.__new__(MyCyClass)
        init_MyCyClass_from_double(my_obj, x0, x1, x2, x3)
        
    cdef init_MyCyClass_from_double(MyCyClass my_obj, double x0, double x1, double x2,  double x3):
        my_obj.x0 = x0
        my_obj.x1 = x1
        my_obj.x2 = x2
        my_obj.x3 = x3
    
    def timefunc(name):
        def timedecorator(f):
            cdef Py_ssize_t L, i
    
            print("Running", name)
            for L in [1, 10, 100, 1000, 10000]:
                start = time.perf_counter() 
                f(L)
                end = time.perf_counter()
                print(format((end-start) / loops * 1e6, "2f"), end=" ")
                sys.stdout.flush()
    
            print("μs")
        return timedecorator
    
    print()
    print("INITIALISATIONS")
    cdef Py_ssize_t loops = 100000
    
    @timefunc("use constructor of non-cdef class with type(input) = float")
    def _(Py_ssize_t L):
        cdef Py_ssize_t i
        
        my_obj = MyPyClass(1., 2., 3., 4.)
        
        for i in range(loops):
            my_obj = MyPyClass(1., 2., 3., 4.)
            
        return my_obj
        
        
    @timefunc("use constructor (cdef) with type(input) = float")
    def _(Py_ssize_t L):
        cdef MyCyClass my_obj = MyCyClass(1., 2., 3., 4.)
        cdef Py_ssize_t i
        
        for i in range(loops):
            # Notice the decimal place to denote 
            my_obj = MyCyClass(1., 2., 3., 4.)
            
        return my_obj
        
    @timefunc("use constructor (cdef) with type(input) = int")
    def _(Py_ssize_t L):
        cdef MyCyClass my_obj = MyCyClass(1, 2, 3, 4)
        cdef Py_ssize_t i
        
        for i in range(loops):
            my_obj = MyCyClass(1, 2, 3, 4)
            
        return my_obj
        
        
    @timefunc("use new (cdef) with double init, input is double")
    def _(Py_ssize_t L):
        cdef MyCyClass my_obj = MyCyClass(1, 2, 3, 4)
        cdef Py_ssize_t i
        
        for i in range(loops):
            my_obj = new_MyCyClass_from_double(1., 2., 3., 4.)
            
        return my_obj    
        
        
    @timefunc("use new (cdef) with double init, input is int")
    def _(Py_ssize_t L):
        cdef MyCyClass my_obj = MyCyClass(1, 2, 3, 4)
        cdef Py_ssize_t i
        
        for i in range(loops):
            new_MyCyClass_from_double(1, 2, 3, 4)
            
        return my_obj    
        
    @timefunc("use new (cdef) and tuple init")
    def _(Py_ssize_t L):
        cdef MyCyClass my_obj = MyCyClass(1., 2., 3., 4.)
        cdef Py_ssize_t i
        
        for i in range(loops):
            my_obj = new_MyCyClass_from_seq((1., 2., 3., 4.))
            
        return my_obj