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


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.