Об'єктно-орієнтоване та векторне програмування


14

Я розривається між об'єктно-орієнтованим та векторним дизайном. Я люблю здібності, структуру та безпеку, які об'єкти надають всій архітектурі. Але в той же час для мене дуже важлива швидкість, і наявність простих змінних плаваючих елементів в масиві дійсно допомагає в векторних мовах / бібліотеках, таких як Matlab або numpy в Python.

Ось фрагмент коду, який я написав, щоб проілюструвати свою думку

Проблема: Додавання номерів нестабільності Tow. Якщо x і y - два числа летючості, сума мінливості становить (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 - це свого роду список з індексом) Тепер я хочу додати два:

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 неправильно, але векторний метод просто так шалено швидко! Чи є дизайн, в якому я можу отримати обидва? Я впевнений, що багато з вас стикалися з подібними варіантами дизайну, як ви це розробили?

Вибір мови тут несуттєвий. Я знаю, що багато хто з вас радить використовувати C ++ або Java, і код може працювати швидше, ніж мови на основі векторних. Але це не сенс. Мені потрібно використовувати Python, оскільки у мене є безліч бібліотек, недоступних іншими мовами. Це моє обмеження. Мені потрібно оптимізувати всередині нього.

І я знаю, що багато людей пропонують паралелізацію, gpgpu тощо. Але я хочу спершу досягти максимальної продуктивності одного ядра, а потім можу паралелізувати обидві версії коду.

Спасибі заздалегідь!


3
Тісно пов'язаний спосіб подумати над цією проблемою: чи варто використовувати структуру масивів (SoA) або масив структур (AoS) для продуктивності? З тим, що SoA легше векторизувати, а AoS бути більш сприятливим для OOP на більшості мов.
Патрік

так @Patrick, якщо ви бачите першу відповідь, я думаю, Барт дав практичний приклад того, що ви робите. Я правий? Зауважую, ви говорите більшість мов, тож чи існують мови, де обидві є близькими за своєю ефективністю?
Рамануй Лал

Відповіді:


9

Як бачите, спосіб OOP дає мені багато безпеки, що люди не будуть додавати Volatility неправильно, але векторний метод просто так шалено швидко! Чи є дизайн, в якому я можу отримати обидва? Я впевнений, що багато з вас стикалися з подібними варіантами дизайну, як ви це розробили?

Проектуйте більші об'єкти. PixelОб'єкт не має кімнату дихання для распараллелен циклу або перетворення зображення GPU або що - небудь подібне. Це за Imageумови, що йому не доведеться пройти через бар'єр підліткового Pixelоб'єкта, щоб отримати дані.


5

Це одна з тих областей, де неможливо дати остаточних відповідей, оскільки це стосується компромісу. Як ви з’ясували, ні OO, ні векторні не завжди є вищими, але все залежить від того, як буде використовуватися програмне забезпечення.

Ви можете спробувати поєднати найкраще з обох і створити і Volatilityоб'єкт, і VolatilitySeriesоб'єкт, де другий концептуально представляє Серію об'єктів волатильності, але внутрішньо використовує метод зберігання, який набагато краще підходить для векторизації обчислень (структура масивів) . Тоді ви просто повинні навчити своїх користувачів, що використовувати VolatilitySeriesнабагато краще Series(Volatility).


Дякую Барту, це гарна ідея. Насправді я пішов таким шляхом у своєму теперішньому дизайні в частинах, де деякі об’єкти, такі як грошові суми, були перероблені таким чином. Але незабаром я зрозумів, що мій код стає рабом цієї конкретної структури даних. Наприклад, якщо у мене є, VolatilitySeriesяк ви пропонуєте, тоді я не можу мати а list, або а tuple(припускаючи, що ви знайомі з Python), а також DataFrameпункти нестабільності. Це мене турбує, тому що тоді моя архітектура не розширюється, і переваги зникають через деякий час. І саме це мене приводить сюди :).
Рамануй Лал

Інше питання полягає в тому, що ніщо не заважає нікому писати такий код volatilitySeries[0] + 3.0, що буде неправильним. Після того, як ви викреслите значення з VolatilitySeries, ви можете перейти до берсерка, тому безпека лише недовговічна. У поліморфному середовищі, де люди не завжди знають, який саме клас використовується, це дуже можливо. І знаєте, ви можете лише так багато навчити своїх користувачів. Я знаю, що ви скажете це, ей, я теж можу зробити те саме, якщо я викручуюся Volatility.value, але ви знаєте, принаймні користувач знає, що зараз він використовує особливе значення.
Рамануй Лал

Деякі можуть також припустити, що переосмислити всі ті звичайні функції, успадковані Seriesв VolatilitySeries, але це перемагає цілі. Тож, що я навчився, пройшовшись по цьому шляху, - це те, що наявність VolatilitySeriesоб'єкта справді працює в довгостроковій перспективі лише тоді, коли окремі клітини мають тип Volatility.
Рамануй Лал

@RamanujLal: Я не знаю пітона досить добре, щоб визначити, чи VolatileSeriesпідхід є життєздатним. Якщо ви вже спробували це, і це не спрацювало, то перед вами важкий вибір між безпекою та швидкістю. Ми не можемо вам допомогти там. (якщо хтось не має блискучої відповіді)
Барт ван Інген Шенау
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.