numba 5.1.@cfunc

被刻印的时光 ゝ 提交于 2020-01-13 20:06:11

5.1.@cfunc                                             # 创建C/C++回调函数;还公开了ctypes指向该回调的回调对象

5.1.@cfunc                                             # 创建C/C++回调函数;还公开了ctypes指向该回调的回调对象



-------------------------------------------------------------------------------------------------------------- 

#实例1.1:

from numba import cfunc



@cfunc("float64(float64, float64)")

def add(x, y):

    return x + y



print(add.ctypes(4.0, 5.0))                      # prints "9.0"

--------------------------------------------------------------------------------------------------------------  

#实例1.2:

import numpy as np

from numba import cfunc



def fun(t):                                                # 纯Python函数

    return np.exp(-t) / t**2



nb_fun = cfunc("float64(float64)")(fun)# 将其编译为C回调



# 将nb_fun对象的ctypes回调传递给scipy.integrate.quad并检查结果是否与纯Python函数相同

import scipy.integrate as si

def run_fun(func):

    return si.quad(func, 1, np.inf)             # 接受常规Python回调或包装在ctypes回调对象中的C回调



run_fun(fun)                                            # (0.14849550677592208, 3.8736750296130505e-10)

run_fun(nb_fun.ctypes)                           # (0.14849550677592208, 3.8736750296130505e-10)



-------------------------------------------------------------------------------------------------------------- 



5.2.指针和阵列存储器处理



# 实例2.1:实现回调:void(double *input, double *output, int m, int n)调用传递C数组



from numba import cfunc, types, carray

c_sig = types.void(types.CPointer(types.double),types.CPointer(types.double),types.intc, types.intc)



@cfunc(c_sig)

def my_callback(in_, out_, m, n):

    in_array = carray(in_, (m, n))

    out_array = carray(out_, (m, n))

    

    for i in range(m):

        for j in range(n):

            out_array[i, j] = 2 * in_array[i, j]

--------------------------------------------------------------------------------------------------------------  

# 实例2.2:处理C结构

# numba可将cffi类型转换为numba Record类型 numba.cffi_support.map_type:



from numba import cffi_support

from cffi import FFI



src = """



/* Define the C struct */

typedef struct my_struct {

   int    i1;

   float  f2;

   double d3;

   float  af4[7];                                         // arrays are supported

} my_struct;



/* Define a callback function */

typedef double (*my_func)(my_struct*, size_t);

"""



ffi = FFI()

ffi.cdef(src)



# Get the function signature from *my_func*

sig = cffi_support.map_type(ffi.typeof('my_func'), 

                       use_record_dtype=True)#True是必需否则返回指向C结构的指针作为void指针



# Make the cfunc

from numba import cfunc, carray



@cfunc(sig)

def foo(ptr, n):

    base = carray(ptr, n)                          # view pointer as an array of my_struct

    tmp = 0

    for i in range(n):

        tmp += base[i].i1 * base[i].f2 / base[i].d3

        tmp += base[i].af4.sum()              # nested arrays are like normal numpy array

    return tmp

--------------------------------------------------------------------------------------------------------------  

# 实例2.3:                                             # 用nb.types.Record.make_c_struct可手动创建遵循C-结构的布局



my_struct = types.Record.make_c_struct([

    # Provides a sequence of 2-tuples i.e. (name:str, type:Type)

    ('i1', types.int32),

    ('f2', types.float32),

    ('d3', types.float64),

    ('af4', types.NestedArray(dtype=types.float32, shape=(7,))),

])

-------------------------------------------------------------------------------------------------------------- 

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!