Я разрываюсь между объектно-ориентированным и векторным дизайном. Я люблю способности, структуру и безопасность, которые объекты дают всей архитектуре. Но в то же время скорость очень важна для меня, и наличие простых переменных с плавающей точкой в массиве действительно помогает в векторных языках / библиотеках, таких как Matlab или numpy в Python.
Вот фрагмент кода, который я написал, чтобы проиллюстрировать мою точку зрения.
Проблема: добавление значений волатильности буксировки. Если x и y - два числа волатильности, сумма волатильности равна (x ^ 2 + y ^ 2) ^ 0.5 (при условии определенного математического условия, но это здесь не важно).
Я хочу выполнить эту операцию очень быстро, и в то же время мне нужно убедиться, что люди не просто неправильно добавляют волатильность (х + у). Оба из них важны.
ОО-дизайн будет выглядеть примерно так:
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)))
(Помимо: опять же, Series в Python - это своего рода список с индексом) Теперь я хочу добавить два:
t1 = datetime.now()
vs3 = vs1 + vs2
t2 = datetime.now()
print t2-t1
Просто добавление выполняется на моей машине за 3,8 секунды, результаты, которые я дал, вообще не включают время инициализации объекта, а только код добавления, который был рассчитан по времени. Если я запускаю то же самое, используя массивы:
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 раз быстрее!
Как вы можете видеть, способ ООП дает мне большую безопасность, так что люди не будут добавлять Волатильность неправильно, но векторный метод просто безумно быстр! Есть ли дизайн, в котором я могу получить оба? Я уверен, что многие из вас сталкивались с подобным выбором дизайна, как вы с этим справились?
Выбор языка здесь не имеет значения. Я знаю, что многие из вас посоветовали бы использовать C ++ или Java, и в любом случае код может работать быстрее, чем векторные языки. Но дело не в этом. Мне нужно использовать Python, потому что у меня есть множество библиотек, недоступных на других языках. Это мое ограничение. Мне нужно оптимизировать в нем.
И я знаю, что многие люди предложили бы распараллеливание, gpgpu и т. Д. Но я хочу сначала максимизировать производительность одного ядра, а затем я могу распараллелить обе версии кода.
Заранее спасибо!
источник
Ответы:
Дизайн больших объектов. У
Pixel
объекта нет передышки для параллельного преобразования изображения или преобразования графического процессора или чего-то подобного. ДействительноImage
, при условии, что он не должен проходить через барьер крошечногоPixel
объекта, чтобы получить данные.источник
Это одна из тех областей, где невозможно дать однозначные ответы, потому что это касается компромисса. Как вы узнали, ни OO, ни Vector-based не всегда лучше, но все зависит от того, как будет использоваться программное обеспечение.
Вы можете попытаться объединить лучшее из обоих и создать как
Volatility
объект, так иVolatilitySeries
объект, где второй концептуально представляет объекты серии изменчивости, но внутренне использует метод хранения, который гораздо лучше подходит для векторизации вычислений (структура массивов). , Тогда вам просто нужно научить своих пользователей, что использованиеVolatilitySeries
намного предпочтительнееSeries(Volatility)
.источник
VolatilitySeries
как вы предлагаете, то я не могу иметьlist
,tuple
или (или (если вы знакомы с Python))DataFrame
элементы волатильности. Это беспокоит меня, потому что тогда моя архитектура плохо масштабируется, и через некоторое время преимущества исчезают. И это то, что приводит меня сюда :).volatilitySeries[0] + 3.0
, что будет неправильно. Как только вы извлекаете значенияVolatilitySeries
, вы можете сходить с ума, поэтому безопасность недолговечна. В полиморфной среде, где люди не всегда знают, какой именно класс используется, это очень возможно. И вы знаете, вы можете только обучить своих пользователей так много. Я знаю, вы скажете, что, эй, я могу сделать то же самое, если вывернуVolatility.value
, но вы знаете, по крайней мере, пользователь теперь знает, что он использует специальное значение.Series
inVolatilitySeries
, но это наносит ущерб всей цели. Итак, что я узнал из этого пути, так это то, что наличиеVolatilitySeries
объекта действительно работает в долгосрочной перспективе, только если отдельные ячейки имеют типVolatility
.VolatileSeries
подход жизнеспособным. Если вы уже попробовали это, и это не сработало, тогда вам приходится выбирать между безопасностью и скоростью. Мы не можем помочь вам там. (если у кого-то еще нет блестящего ответа)