gpt4 book ai didi

python - 如何使用指针在 Numba 中包装 CFFI 函数

转载 作者:行者123 更新时间:2023-12-03 23:54:20 24 4
gpt4 key购买 nike

这应该是一项简单的任务,但我找不到如何将标量值的指针传递给 Numba 函数中的 CFFI 函数的方法。使用 ffi.from_buffer 传递指向数组的指针没有问题.

示例函数

import cffi

ffi = cffi.FFI()
defs="void foo_f(int a,double *b);"
ffi.cdef(defs, override=True)
source="""
#include <stdio.h>;
void foo_f(int a,double *b){
printf("%i",a);
printf(" ");
printf("%f",b[0]);
}

"""
ffi.set_source(module_name="foo",source=source)
ffi.compile()

传递指向数组的指针
import numpy as np
import numba as nb
import cffi
ffi = cffi.FFI()
import numpy as np
import ctypes
import foo
nb.cffi_support.register_module(foo)
foo_f = foo.lib.foo_f

@nb.njit()
def Test(a,b):
a_wrap=np.int32(a)
#This works for an array
b_wrap=ffi.from_buffer(b.astype(np.float64))
foo_f(a_wrap,b_wrap)


a=64.
b=np.ones(5)
Test(a,b)

这没有问题,但我该如何修改 Test函数取一个标量值 b=5.不修改 CFFI 函数本身?

最佳答案

使用 Numba 通过引用传递标量值
为了获得有用的时间,我稍微修改了包装函数。该函数只是将一个标量(通过值传递)添加到一个标量 b(通过引用传递)。
使用内在函数的方法的优缺点

  • 仅在 nopython 模式下工作
  • 运行时间短的 C 或 Fortran 函数更快 ( real-world example )

  • 示例函数
    import cffi

    ffi = cffi.FFI()
    defs="void foo_f(double a,double *b);"
    ffi.cdef(defs, override=True)
    source="""
    void foo_f(double a,double *b){
    b[0]+=a;
    }
    """
    ffi.set_source(module_name="foo",source=source)
    ffi.compile()
    使用临时数组的包装器
    这很简单,但需要分配一个大小为 1 的数组,这很慢。
    import numpy as np
    import numba as nb
    from numba import cffi_support
    import cffi
    ffi = cffi.FFI()
    import foo

    nb.cffi_support.register_module(foo)
    foo_f = foo.lib.foo_f

    @nb.njit("float64(float64,float64)")
    def method_using_arrays(a,b):
    b_arr=np.empty(1,dtype=np.float64)
    b_arr[0]=b
    b_arr_ptr=b_wrap=ffi.from_buffer(b_arr)
    foo_f(a,b_arr_ptr)
    return b_arr[0]
    使用内在函数的包装器
    from numba import types
    from numba.extending import intrinsic
    from numba import cgutils

    @intrinsic
    def ptr_from_val(typingctx, data):
    def impl(context, builder, signature, args):
    ptr = cgutils.alloca_once_value(builder,args[0])
    return ptr
    sig = types.CPointer(data)(data)
    return sig, impl

    @intrinsic
    def val_from_ptr(typingctx, data):
    def impl(context, builder, signature, args):
    val = builder.load(args[0])
    return val
    sig = data.dtype(data)
    return sig, impl

    @nb.njit("float64(float64,float64)")
    def method_using_intrinsics(a,b):
    b_ptr=ptr_from_val(b)
    foo_f(a,b_ptr)
    return val_from_ptr(b_ptr)
    计时
    #Just call the wrapped function a few times
    @nb.njit()
    def timing_method_using_intrinsics(a,b):
    for i in range(1000):
    b=method_using_intrinsics(a,b)
    return b

    #Just call the wrapped function a few times
    @nb.njit()
    def timing_method_using_arrays(a,b):
    for i in range(1000):
    b=method_using_arrays(a,b)
    return b

    a=1.
    b=1.

    %timeit timing_method_using_intrinsics(a,b)
    #5.15 µs ± 33.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    %timeit timing_method_using_arrays(a,b)
    #121 µs ± 601 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

    关于python - 如何使用指针在 Numba 中包装 CFFI 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51541302/

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