Python + alglib + NumPy: как избежать преобразования массивов в списки?

Контекст: Недавно я обнаружил библиотеку alglib (для численных вычислений), которая, похоже, была тем, что я искал (надежная интерполяция, анализ данных ...) и не мог найти в numpy или scipy.

Однако меня беспокоит тот факт, что (например, для интерполяции) он не принимает массив numpy в качестве допустимого формата ввода, а только обычные объекты списка Python.

Проблема: Я немного покопался в коде и документации и обнаружил (как и ожидалось), что этот формат списка предназначен только для перехода, поскольку библиотека в любом случае преобразует его в ctypes (библиотека cpython - это просто интерфейс для базового C / C ++ библиотека).

Вот что меня беспокоит: внутри моего кода я работаю с множеством массивов, потому что это сильно повышает производительность научных вычислений, которые я выполняю над ним. Поэтому я опасаюсь, что необходимость преобразования любых данных, переданных в подпрограммы 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%, что огромно мне ...

9
задан Eric O Lebigot 26 February 2012 в 02:36
поделиться