面向对象与基于矢量的编程

2024-04-28 09:07:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我在面向对象和基于向量的设计之间左右为难。我喜欢物体赋予整个建筑的能力、结构和安全性。但同时,速度对我来说非常重要,在数组中使用简单的浮点变量对于基于向量的语言/库(如Matlab或Python中的numpy)确实有帮助。在

下面是我写的一段代码来说明我的观点

问题:增加两个波动率数字。如果x和y是两个波动率数,则波动率之和为(x^2+y^2)^0.5(假设一定的数学条件,但这在这里并不重要)。在

我想很快地执行这个操作,同时我需要确保人们不会以错误的方式(x+y)增加波动性。这两者都很重要。在

基于OO的设计应该是这样的:

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只是一个覆盖“+”运算符的函数)

假设我添加了两个波动性值列表

^{pr2}$

(旁白:同样,Python中的一个系列类似于一个带有索引的列表) 现在我要加上两个:

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方法给了我很多安全性,人们不会用错误的方式添加波动性,但是向量方法的速度太快了!有没有一种设计能让我两者兼得?我相信你们很多人都遇到过类似的设计选择,你们是怎么做到的?在

语言的选择在这里是无关紧要的。我知道你们中的很多人建议使用C++或java,并且代码可能比基于向量的语言运行得快。但这不是重点。我需要使用Python,因为我有许多其他语言无法使用的库。这是我的限制。我需要优化它。在

我知道,很多人会建议并行化,gpgpu等等,但我想先最大限度地提高单核性能,然后我可以并行化两个版本的代码。在

提前谢谢!在


Tags: 代码selfnumpy语言datetimevaluedef向量
2条回答

你可以在向量化操作之上进行抽象、封装、代码重用等(通过OOP或其他方式)。您只需选择正确的粒度:您的单元抽象(object)应该是多个值,以匹配矢量化的实现。据我所知,volatility没有复数形式,但对于您的特定用例,可能有一个更合适的术语(您的波动性值集意味着什么)。在

是的,这意味着性能问题会影响抽象和API(但无论如何都会发生这种情况)。不,影响不一定是简化抽象,甚至是漏洞百出的抽象。它只是改变了抽象的形状。事实上,如果只对所有值同时进行操作,这甚至可能为其余代码生成更方便的API。在

对于这些情况,一个可能的解决方案是后退一步:您真的需要或想将单个值表示为对象吗?如果您的对象是Volatile的整个数组(或序列)呢?你可以两全其美。在

即使对单个Volatile对象有一些用途,也可以实现flyweight pattern,其中Volatile对象只是数组中位置的包装器,所有方法都将在数组上操作。在

相关问题 更多 >