オブジェクト指向とベクトルベースのプログラミング


14

私はオブジェクト指向とベクターベースのデザインの間で引き裂かれています。オブジェクトがアーキテクチャ全体に与える能力、構造、安全性が大好きです。しかし同時に、速度は私にとって非常に重要であり、配列に単純なフロート変数があると、MatlabやPythonのnumpyなどのベクトルベースの言語/ライブラリで非常に役立ちます。

これが私のポイントを説明するために書いたコードです

問題:トウのボラティリティ値を追加します。xとyが2つのボラティリティ数である場合、ボラティリティの合計は(x ^ 2 + y ^ 2)^ 0.5です(特定の数学的条件を仮定しますが、ここでは重要ではありません)。

この操作を非常に高速に実行すると同時に、人々がボラティリティを間違った方法(x + y)で追加しないようにする必要があります。これらは両方とも重要です。

オブジェクト指向ベースのデザインは次のようになります。

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

(余談:Pythonを初めて使用する場合__add__は、単なる+演算子をオーバーライドする関数です)

ボラティリティ値のトウリストを追加するとしましょう

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

(余談ですが、PythonのSeriesはインデックス付きのリストのようなものです)次に、2つを追加します。

t1 = datetime.now()
vs3 = vs1 + vs2
t2 = datetime.now()
print t2-t1

私のマシンでは3.8秒で加算が実行されますが、私が与えた結果にはオブジェクトの初期化時間は含まれず、時間計測された加算コードのみが含まれています。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

0.03秒で実行されます。それは100倍以上高速です!

ご覧のとおり、OOPの方法は、人々がVolatilityを間違った方法で追加することのない多くのセキュリティを提供しますが、vectorメソッドは非常に高速です!両方を入手できるデザインはありますか?多くの人が似たようなデザインの選択に出くわしたと思いますが、どうやってそれを解決したのですか?

ここでの言語の選択は重要ではありません。多くの場合、C ++またはJavaを使用することをお勧めします。コードは、ベクターベースの言語よりも高速に実行される可能性があります。しかし、それはポイントではありません。Pythonを使用する必要があるのは、他の言語では使用できないライブラリが多数あるためです。それが私の制約です。その中で最適化する必要があります。

そして、多くの人が並列化やgpgpuなどを提案することを知っています。しかし、最初にシングルコアのパフォーマンスを最大化したいので、それからコードの両方のバージョンを並列化できます。

前もって感謝します!


3
この問題について密接に関連する考え方:パフォーマンスのために配列の構造(SoA)または構造の配列(AoS)を使用する必要がありますか?ほとんどの言語では、SoAのベクトル化が容易になり、AoSのOOPフレンドリが向上しています。
パトリック

はい、@ Patrick、あなたが最初の答えを見るならば、バートはあなたがしているポイントの実用的な例を与えたと思います。私は正しいですか?ほとんどの言語を言っていることに気付きましたが、両方のパフォーマンスが近い言語はありますか?
ラマヌジラル

回答:


9

ご覧のとおり、OOPの方法は、人々がVolatilityを間違った方法で追加することのない多くのセキュリティを提供しますが、vectorメソッドは非常に高速です!両方を入手できるデザインはありますか?多くの人が似たようなデザインの選択に出くわしたと思いますが、どうやってそれを解決したのですか?

より大きなオブジェクトを設計します。Pixelオブジェクトは、並列化されたループ又はGPU画像変換、またはそのようなもののための余裕を持っていません。Imageそれはティーニー用の障壁を通過する必要はありません提供しないPixelデータを取得するためのオブジェクト。


5

これはトレードオフに関するものであるため、明確な答えを出すことが不可能な領域の1つです。おわかりのように、OOもベクターベースも常に優れているわけではありませんが、すべてはソフトウェアの使用方法に依存します。

両方の長所を組み合わせてVolatilityオブジェクトとオブジェクトの両方を作成しようとすることができVolatilitySeriesます。2番目は概念的に一連のボラティリティオブジェクトを表しますが、内部的には計算(ベクトルの配列)のベクトル化に適したストレージメソッドを使用します。次に、を使用することVolatilitySeriesがはるかに望ましいことをユーザーに教育する必要がありますSeries(Volatility)


バート、ありがとう。実際、私は現在の部品の設計でそのようにしており、金額などのオブジェクトがそのように再設計されています。しかしすぐに、コードがその特定のデータ構造のスレーブになることに気付きました。たとえばVolatilitySeries、私があなたが提案するように持っている場合、私はlist、またはtupleあなたが(あなたがPythonに精通していると仮定して)DataFrame揮発性アイテムを持つことはできません。それは気になります。なぜなら、私のアーキテクチャはうまく拡張できず、しばらくするとメリットが消えてしまうからです。そして、それが私をここに連れてきます:)。
ラマヌジラル

もう1つの問題は、のようなコードを書くことを誰も妨げていないvolatilitySeries[0] + 3.0ことです。から値をリグリングするとVolatilitySeries、凶暴化する可能性があるため、安全性は短命です。使用されている正確なクラスを常に認識しているとは限らないポリモーフィック環境では、これは非常に可能です。そして、あなたはあなたのユーザーをそれほど教育することができるだけです。私はあなたが言うことを知っています、もし私がうごめくなら同じことをすることVolatility.valueができますが、あなたは知っています、少なくともユーザーは彼が特別な値を使用していることを知っています。
ラマヌジラル

また、Seriesin から継承された通常の関数をすべてオーバーライドすることを提案するかもしれませんVolatilitySeriesが、それは目的全体を無効にします。その道を進むことから学んだことはVolatilitySeries、個別のセルがタイプである場合には、長い目で見ればオブジェクトが本当にうまくいくということVolatilityです。
ラマヌジラル

@RamanujLal:VolatileSeriesアプローチが実行可能かどうかを判断するのに十分なPythonの知識がありません。すでに試してみて、うまくいかなかった場合は、安全性と速度のどちらを選択するかを決めるのは難しい選択です。お手伝いできません。(他の誰かが素晴らしい答えを持たない限り)
バートヴァンインゲンシェナウ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.