Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.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
C++ Python+;alglib&x2B;NumPy:如何避免将数组转换为列表?_C++_Python_Performance_Numpy_Alglib - Fatal编程技术网

C++ Python+;alglib&x2B;NumPy:如何避免将数组转换为列表?

C++ Python+;alglib&x2B;NumPy:如何避免将数组转换为列表?,c++,python,performance,numpy,alglib,C++,Python,Performance,Numpy,Alglib,上下文: 我最近发现了(用于数值计算),这似乎是我一直在寻找的东西(鲁棒插值、数据分析…),但在numpy或scipy中找不到 但是,我担心的是,它不接受numpy数组作为有效的输入格式,而只接受常规python列表对象 问题: 我对代码和文档进行了深入研究,发现(正如预期的那样)此列表格式只是用于转换,因为库会将其转换为ctypes(cpython库只是底层C/C++库的接口) 这就是我担心的地方:在我的代码中,我正在使用numpy数组,因为这对于我正在执行的科学计算来说是一个巨大的性能提升。

上下文: 我最近发现了(用于数值计算),这似乎是我一直在寻找的东西(鲁棒插值、数据分析…),但在numpy或scipy中找不到

但是,我担心的是,它不接受numpy数组作为有效的输入格式,而只接受常规python列表对象

问题: 我对代码和文档进行了深入研究,发现(正如预期的那样)此列表格式只是用于转换,因为库会将其转换为ctypes(cpython库只是底层C/C++库的接口)

这就是我担心的地方:在我的代码中,我正在使用numpy数组,因为这对于我正在执行的科学计算来说是一个巨大的性能提升。因此,我担心必须将传递给alglib例程的任何数据转换为list(将转换为ctypes)将对性能产生巨大影响(我使用的数组可能有数十万个浮点,并且有数千个数组)

问题: 您是否认为我确实会有性能损失,或者您认为我应该开始修改alglib代码(仅python接口),以便它可以接受numpy数组,并且只进行一次转换(从numpy数组到ctype)?我甚至不知道这是否可行,因为这是一个相当大的图书馆。。。 也许你们有更好的想法或建议(即使是在相似但不同的库上)


编辑 我的问题似乎没有引起太多的兴趣,或者我的问题不清楚/不相关。或许没有人有解决方案或建议,但我怀疑周围这么多专家:) 无论如何,我已经写了一个小的,快速的,肮脏的测试代码来说明这个问题

#!/usr/bin/env python

import xalglib as al
import timeit
import numpy as np

def func(x):
    return (3.14 *x**2.3 + x**3 -x**2.34 +x)/(1.+x)**2

def fa(x, y, val=3.14):
    s = al.spline1dbuildakima(x, y)
    return (al.spline1dcalc(s, val), func(val))

def fb(x, y, val=3.14):
    _x = list(x)
    _y = list(y)
    s = al.spline1dbuildakima(_x, _y)
    return (al.spline1dcalc(s, val), func(val))

ntot = 10000
maxi = 100
x = np.random.uniform(high=maxi, size=ntot)
y = func(x)
xl = list(x)
yl = list(y)

print "Test for len(x)=%d, and x between [0 and %.2f):" % (ntot, maxi)
print "Function: (3.14 *x**2.3 + x**3 -x**2.34 +x)/(1.+x)**2"
a, b = fa(xl, yl)
err = np.abs(a-b)/b * 100
print "(x=3.14) interpolated, exact =", (a, b)
print "(x=3.14) relative error should be <= 1e-2: %s (=%.2e)" % ((err <= 1e-2), err)

if __name__ == "__main__":
    t = timeit.Timer(stmt="fa(xl, yl)", setup="from __main__ import fa, xl, yl, func")
    tt = timeit.Timer(stmt="fb(x, y)", setup="from __main__ import fb, x, y, func")
    v = 1000 * t.timeit(number=100)/100
    vv = 1000 * tt.timeit(number=100)/100
    print "%.2f usec/pass" % v
    print "%.2f usec/pass" % vv
    print "%.2f %% less performant using numpy arrays" % ((vv-v)/v*100.)
#/usr/bin/env python
将xalglib作为al导入
导入时间信息
将numpy作为np导入
def func(x):
返回(3.14*x**2.3+x**3-x**2.34+x)/(1.+x)**2
def fa(x,y,val=3.14):
s=al.花键1dbuildakima(x,y)
报税表(会计科目、会计科目、会计科目)
def fb(x,y,val=3.14):
_x=列表(x)
_y=列表(y)
s=al.夹板1dbuildakima(_x,_y)
报税表(会计科目、会计科目、会计科目)
ntot=10000
最大值=100
x=np.随机.均匀(高=最大值,大小=ntot)
y=func(x)
xl=列表(x)
yl=列表(y)
打印“len(x)=%d的测试,以及[0和%.2f]之间的x):”%(ntot,maxi)
打印“功能:(3.14*x**2.3+x**3-x**2.34+x)/(1.+x)**2”
a、 b=fa(xl,yl)
误差=np.abs(a-b)/b*100
打印“(x=3.14)插值,精确=”,(a,b)

打印(x=3.14)相对误差应该是使C++ AlgLIB接受数字数组是可行的:SciPy这样做。问题是它有多困难。你可能想试试半自动C++。→ Python包装程序,如(从我将开始的程序开始–警告:我不是专家):


关于另一个主题:过去我在SciPy中成功地使用了插值样条线。不过,我不确定这是否足以满足您的需要,因为您在SciPy中没有找到您想要的所有内容。

除了EOL的答案,您还可以尝试

为了生成一个Python接口,该接口处理NumPy数组,但使用适当的参数调用底层C/C++


我发现文档足够清晰,可以为一个小型的科学C库执行此操作,而之前从未执行过此操作,也没有丰富的C和Python接口经验。

您可以创建自己的wrap函数,将numpy数组的数据缓冲区直接传递给向量的数据指针,这不会复制数据,并加快wrap速度下面的代码将x.ctypes.data传递给x_vector.ptr.p_ptr,其中x是一个numpy数组

传递numpy数组时,必须确保该数组的元素位于连续内存中

import xalglib as al
import numpy as np
import ctypes

def spline1dbuildakima(x, y):
    n = len(x)
    _error_msg = ctypes.c_char_p(0)
    __c = ctypes.c_void_p(0)
    __n = al.c_ptrint_t(n)
    __x = al.x_vector(cnt=n, datatype=al.DT_REAL, owner=al.OWN_CALLER, 
                      last_action=0,ptr=al.x_multiptr(p_ptr=x.ctypes.data))
    __y = al.x_vector(cnt=n, datatype=al.DT_REAL, owner=al.OWN_CALLER, 
                      last_action=0,ptr=al.x_multiptr(p_ptr=y.ctypes.data))

    al._lib_alglib.alglib_spline1dbuildakima(
        ctypes.byref(_error_msg), 
        ctypes.byref(__x), 
        ctypes.byref(__y), 
        ctypes.byref(__n), 
        ctypes.byref(__c))

    __r__c = al.spline1dinterpolant(__c)
    return __r__c    

def func(x):
    return (3.14 *x**2.3 + x**3 -x**2.34 +x)/(1.+x)**2

def fa(x, y, val=3.14):
    s = spline1dbuildakima(x, y)
    return al.spline1dcalc(s, val), func(val)

def fb(x, y, val=3.14):
    s = al.spline1dbuildakima(x, y)
    return al.spline1dcalc(s, val), func(val)

ntot = 10000
maxi = 100
x = np.random.uniform(high=maxi, size=ntot)
y = func(x)
xl = list(x)
yl = list(y)

import time
start = time.clock()
for i in xrange(100):
    a, b = fa(x, y)
print time.clock()-start
err = np.abs(a-b)/b * 100
print a, b, err

start = time.clock()
for i in xrange(100):
    a, b = fb(xl, yl)
print time.clock()-start
err = np.abs(a-b)/b * 100
print a, b, err
输出为:

0.722314760822 <- seconds of numpy array version
3.68672728107 3.68672785313 1.55166878281e-05
3.22011891502  <- seconds of list version
3.68672728107 3.68672785313 1.55166878281e-05

0.722314760822感谢您的回答。SciPy软件包中的样条曲线按预期工作,但我缺少了一些样条曲线,如Akima(我确实有一些数据需要线性插值,但“性能不好”)“足以使用三次或更高阶样条曲线,而不会产生一些不必要的伪影(如结果中的振荡)此外,AlgLB有一些其他的数据分析和统计工具,Spyy没有,所以我使用这种外部库是有意义的。对于包层,似乎AlgLB开发人员已经使用了一个用于C+Python…@ MHVELL:可以包装C++代码,以便它直接使用NUMPY数组而不是Python列表;令人惊讶的是,alglib的Python包装不允许这样做。自己包装所需的函数可能比修改alglib Python包装更容易:如果需要的话,您将能够使用自己的包装来更轻松地跟踪alglib的更新。我列出的三个包装应该对您有很大帮助。哦,好吧:)我不是在Python中有专家,我甚至可以尝试一下。谢谢。MHAVEL:谢谢。我不擅长为Python包C++代码,但是研究一些列出的C++包装可能是一个很好的投资,对于有兴趣的快速科学计算。谢谢你的回答,我来看看。你可以所有
x=np.ascontiguousarray(x)
以确保它在内存中是连续的。哇,太好了!非常感谢HYRY。我以前从未使用过包装方法,所以我正在阅读一些EOL很好地指出的文档。您的示例对我来说是一个好时机,所以我现在有了一些具体的培训内容。@Sebastian感谢您的评论。这也将对我有所帮助。
0.722314760822 <- seconds of numpy array version
3.68672728107 3.68672785313 1.55166878281e-05
3.22011891502  <- seconds of list version
3.68672728107 3.68672785313 1.55166878281e-05