背景:
我最近发现了alglib库(用于数值计算),它似乎是我正在寻找的东西(强大的插值,数据分析...),在numpy或scipy中无法找到。
运行它,我得到了以下结果:
然而,我担心的是(例如对于插值),它不接受numpy数组作为有效的输入格式,而仅仅接受常规的python列表对象。
问题: 我深入研究了代码和文档,并发现(如预期的那样)这个列表格式只是过渡,因为该库将无论如何将其转换为ctypes(cpython库只是底层C / C ++库的接口)。这就是我的担忧所在:在我的代码中,我使用numpy数组工作,因为它对我进行的科学计算是一个巨大的性能提升。因此,我担心必须将传递给alglib例程的任何数据转换为列表(将转换为ctypes)将对性能产生巨大影响(我正在处理可能包含数百万个浮点数的数组,并且有数千个数组)。
问题: 您认为我确实会有性能损失,还是您认为我应该开始修改alglib代码(仅修改python接口),以便它可以接受numpy数组,并进行一次转换(从numpy数组到ctypes)?我甚至不知道这是否可行,因为它是一个相当大的库... 也许您们有更好的想法或建议(即使是关于类似但不同的库)...编辑
似乎我的问题没有引起太多关注,或者我的问题不清楚/不相关。或者可能没有人有解决方案或建议,但我怀疑有这么多专家在周围 :) 无论如何,我编写了一个小的、快速而肮脏的测试代码来说明问题...
#!/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.)
运行它,我得到了以下结果:
"""
Test for len(x)=10000, and x between [0 and 100.00):
Function: (3.14 *x**2.3 + x**3 -x**2.34 +x)/(1.+x)**2
(x=3.14) interpolated, exact = (3.686727834705164, 3.6867278531266905)
(x=3.14) relative error should be <= 1e-2: True (=5.00e-07)
25.85 usec/pass
28.46 usec/pass
10.09 % less performant using numpy arrays
"""
性能损失在8%至14%之间波动,对我来说非常巨大...
x = np.ascontiguousarray(x)
来确保它在内存中是连续的。 - jfs