Question

Contexte: J'ai découvert récemment l' alglib bibliothèque (pour le calcul numérique), ce qui semble être la chose que je cherchais (robuste interpolation, analyse de données...) et ne pouvait pas vraiment se trouver dans numpy ou scipy.

Cependant, je suis préoccupé par le fait que (eg.pour l'interpolation) il n'accepte pas un tableau numpy comme valide le format d'entrée, mais seulement régulière python les objets de la liste.

Problème: J'ai creusé un peu dans le code et la documentation, et trouvé (comme prévu) que ce format de liste est juste pour la transition, depuis la bibliothèque sera de toute façon de le convertir en ctypes (le disponible de la bibliothèque est juste une interface pour le C/C++ de la bibliothèque).

C'est là que vient mon souci:à l'intérieur de mon code, je travaille avec des tableaux numpy, parce que c'est un gros boost de performance pour le calcul scientifique, je suis d'effectuer sur elle.J'ai donc peur d'avoir à convertir les données transmises à alglib routines dans la liste (qui sera convertie en ctypes) aura un impact énorme sur les performances (je travaille avec des tableaux qui pourraient avoir des centaines de milliers de chars à l'intérieur, et avec des milliers de tableaux).

Question: Pensez-vous que je vais avoir une perte de performance, ou pensez-vous que je devrais commencer à modifier le alglib code (uniquement le python interface) afin qu'il puisse accepter les tableaux numpy, et de faire une seule conversion (à partir de tableaux numpy pour ctypes)?Je ne sais même pas si cela est possible, car il est tout à fait une grande bibliothèque...Peut-être que vous les gars ont de meilleures idées ou des suggestions (même sur similaires mais différentes bibliothèques)...


MODIFIER

Il semble que mon problème n'est pas l'objet de beaucoup d'intérêt, ou que ma question n'est pas claire et pertinente.Ou peut-être personne n'a une solution ou des conseils, mais j'en doute avec de nombreux experts de partout :) De toute façon, j'ai écrit un petit, rapide et sale de test de code pour illustrer le problème...

#!/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.)

et en l'exécutant, j'obtiens:

"""
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
"""

La perte de performances oscille entre 8% et 14%, ce qui est énorme pour moi...

Était-ce utile?

La solution

Faire le C++ alglib accepter les tableaux NumPy est certainement faisable:SciPy fait cela.La question est de savoir vraiment combien il est difficile.Vous voudrez peut-être essayer un de l'semi-automatique C++ → Python habillage de programme, comme l' (en commençant par celui que je voudrais commencer avec l'avertissement:Je ne suis pas expert):

Sur un autre sujet:J'ai utilisé l'interpolation spline dans SciPy avec succès dans le passé.Je ne suis pas sûr que ce serait suffisant pour vos besoins, cependant, puisque vous n'avez pas trouvez tout ce que vous voulez dans SciPy.

Autres conseils

Vous pouvez créer votre propre écharpe fonction que de passer un tableau numpy du tampon de données pour le vecteur de pointeur de données directement, ce ne sera pas copier les données, et de l'accélération de votre écharpe fonction beaucoup.Le code suivant pass x.ctypes.les données de x_vector.ptr.p_ptr, où x est un tableau numpy.

lorsque vous passez un tableau numpy, vous devez vous assurer que la matrice a est des éléments dans la mémoire contiguë.Le code suivant ne débite pas vérifier ce point.

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

La sortie est:

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

En plus de EOL de réponses, vous pouvez également essayer

afin de générer une interface Python qui traite avec des tableaux NumPy mais les appels de sous-jacents C/C++ avec les arguments appropriés.

J'ai trouvé les docs suffisamment claire pour ce faire, pour un petit scientifique de la bibliothèque C, sans l'avoir jamais fait ça avant, ou ayant eu une grande expérience avec l'interfaçage C et Python.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top