Je suis partagé entre la conception orientée objet et la conception vectorielle. J'adore les capacités, la structure et la sécurité que les objets donnent à toute l'architecture. Mais en même temps, la vitesse est très importante pour moi, et avoir de simples variables flottantes dans un tableau aide vraiment dans les langages / bibliothèques vectoriels comme Matlab ou numpy en Python.
Voici un morceau de code que j'ai écrit pour illustrer mon propos
Problème: ajout de numéros de volatilité Tow. Si x et y sont deux nombres de volatilité, la somme de la volatilité est (x ^ 2 + y ^ 2) ^ 0,5 (en supposant une certaine condition mathématique mais ce n'est pas important ici).
Je veux effectuer cette opération très rapidement, et en même temps, je dois m'assurer que les gens n'ajoutent pas seulement la volatilité de la mauvaise façon (x + y). Ces deux éléments sont importants.
La conception basée sur OO ressemblerait à ceci:
from datetime import datetime
from pandas import *
class Volatility:
def __init__(self,value):
self.value = value
def __str__(self):
return "Volatility: "+ str(self.value)
def __add__(self,other):
return Volatility(pow(self.value*self.value + other.value*other.value, 0.5))
(En plus: pour ceux qui sont nouveaux dans Python, __add__
c'est juste une fonction qui remplace l' +
opérateur)
Disons que j'ajoute des listes de remorquage des valeurs de volatilité
n = 1000000
vs1 = Series(map(lambda x: Volatility(2*x-1.0), range(0,n)))
vs2 = Series(map(lambda x: Volatility(2*x+1.0), range(0,n)))
(À côté: Encore une fois, une série en Python est une sorte de liste avec un index) Maintenant, je veux ajouter les deux:
t1 = datetime.now()
vs3 = vs1 + vs2
t2 = datetime.now()
print t2-t1
L'addition s'exécute en 3,8 secondes sur ma machine, les résultats que j'ai donnés n'incluent pas du tout le temps d'initialisation de l'objet, c'est le seul code d'addition qui a été chronométré. Si je lance la même chose en utilisant des tableaux numpy:
nv1 = Series(map(lambda x: 2.0*x-1.0, range(0,n)))
nv2 = Series(map(lambda x: 2.0*x+1.0, range(0,n)))
t3 = datetime.now()
nv3 = numpy.sqrt((nv1*nv1+nv2*nv2))
t4 = datetime.now()
print t4-t3
Il s'exécute en 0,03 secondes. C'est plus de 100 fois plus rapide!
Comme vous pouvez le voir, la méthode OOP me donne beaucoup de sécurité pour que les gens n'ajoutent pas la volatilité de la mauvaise façon, mais la méthode vectorielle est tellement rapide et folle! Existe-t-il un design dans lequel je peux obtenir les deux? Je suis sûr que beaucoup d'entre vous ont rencontré des choix de conception similaires, comment avez-vous procédé?
Le choix de la langue ici est sans importance. Je sais que beaucoup d'entre vous conseillent d'utiliser C ++ ou Java, et le code peut s'exécuter plus rapidement que les langages vectoriels. Mais ce n'est pas le but. J'ai besoin d'utiliser Python, car j'ai une multitude de bibliothèques non disponibles dans d'autres langues. Voilà ma contrainte. J'ai besoin d'optimiser en son sein.
Et je sais que beaucoup de gens suggéreraient la parallélisation, gpgpu, etc. Mais je veux d'abord maximiser les performances du noyau unique, puis je peux paralléliser les deux versions de code.
Merci d'avance!
la source
Réponses:
Concevez des objets plus gros. Un
Pixel
objet n'a pas de marge de manœuvre pour une boucle parallélisée ou des transformations d'image GPU ou quelque chose comme ça. UneImage
bête à condition de ne pas avoir à passer la barrière d'un petitPixel
objet pour accéder aux données.la source
C'est l'un de ces domaines où il est impossible de donner des réponses définitives, car il s'agit d'un compromis. Comme vous l'avez découvert, ni OO, ni basé sur des vecteurs n'est toujours supérieur, mais tout dépend de la façon dont le logiciel sera utilisé.
Vous pouvez essayer de combiner le meilleur des deux et créer à la fois un
Volatility
objet et unVolatilitySeries
objet, où le second représente conceptuellement une série d'objets de volatilité, mais utilise en interne une méthode de stockage bien mieux adaptée à la vectorisation des calculs (une structure de tableaux) . Ensuite, il vous suffit d'éduquer vos utilisateurs sur le fait qu'ilVolatilitySeries
est préférable d' utiliserSeries(Volatility)
.la source
VolatilitySeries
comme vous le suggérez, je ne peux pas avoir unlist
, ou untuple
ou (en supposant que vous connaissez Python) unDataFrame
des éléments de volatilité. Cela me dérange, car alors mon architecture ne s'adapte pas bien et les avantages disparaissent après un certain temps. Et c'est ce qui m'amène ici :).volatilitySeries[0] + 3.0
, ce qui sera faux. Une fois que vous avez supprimé les valeursVolatilitySeries
, vous pouvez devenir fou, donc la sécurité n'est que de courte durée. Dans un environnement polymorphe où les gens ne sont pas toujours conscients de la classe exacte utilisée, cela est hautement possible. Et vous savez, vous ne pouvez éduquer que vos utilisateurs. Je sais que vous direz cela, hé je peux aussi faire la même chose si je me tortilleVolatility.value
, mais vous savez, au moins l'utilisateur est conscient maintenant qu'il utilise une valeur spéciale.Series
inVolatilitySeries
, mais cela va à l'encontre de l'objectif global. Donc, ce que j'ai appris en descendant ce chemin, c'est qu'avoir unVolatilitySeries
objet ne fonctionne vraiment à long terme que si les cellules individuelles sont de typeVolatility
.VolatileSeries
approche est viable. Si vous l'avez déjà essayé et que cela n'a pas fonctionné, vous avez un choix difficile à faire entre sécurité et vitesse. Nous ne pouvons pas vous y aider. (sauf si quelqu'un d'autre a une réponse brillante)