Pemrograman berorientasi objek vs berbasis vektor

14

Saya terpecah antara berorientasi objek dan desain berbasis vektor. Saya suka kemampuan, struktur, dan keamanan yang diberikan benda-benda ke seluruh arsitektur. Tetapi pada saat yang sama, kecepatan sangat penting bagi saya, dan memiliki variabel float sederhana dalam array sangat membantu dalam bahasa berbasis vektor / perpustakaan seperti Matlab atau numpy in Python.

Ini adalah sepotong kode yang saya tulis untuk mengilustrasikan poin saya

Masalah: Menambahkan angka volatilitas Tow. Jika x dan y adalah dua angka volatilitas, jumlah volatilitasnya adalah (x ^ 2 + y ^ 2) ^ 0,5 (dengan asumsi kondisi matematika tertentu tetapi itu tidak penting di sini).

Saya ingin melakukan operasi ini dengan sangat cepat, dan pada saat yang sama saya perlu memastikan bahwa orang tidak hanya menambahkan volatilitas dengan cara yang salah (x + y). Keduanya penting.

Desain berbasis OO akan seperti ini:

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

(Selain: Bagi mereka yang baru mengenal Python, __add__hanyalah fungsi yang menimpa +operator)

Katakanlah saya menambahkan daftar deretan nilai volatilitas

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

(Selain: Sekali lagi, Seri dalam Python adalah semacam daftar dengan indeks) Sekarang saya ingin menambahkan keduanya:

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

Hanya penambahan berjalan dalam 3,8 detik pada mesin saya, hasil yang saya berikan tidak termasuk waktu inisialisasi objek sama sekali, itu hanya kode penambahan yang telah diatur waktunya. Jika saya menjalankan hal yang sama menggunakan numpy array:

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

Ini berjalan dalam 0,03 detik. Itu lebih dari 100 kali lebih cepat!

Seperti yang Anda lihat, cara OOP memberi saya banyak keamanan sehingga orang tidak akan menambahkan Volatilitas dengan cara yang salah, tetapi metode vektor sangat cepat gila! Apakah ada desain di mana saya bisa mendapatkan keduanya? Saya yakin banyak dari Anda telah mengalami pilihan desain yang serupa, bagaimana Anda mengatasinya?

Pilihan bahasa di sini tidak penting. Saya tahu banyak dari Anda akan menyarankan agar menggunakan C ++ atau Java, dan kode dapat berjalan lebih cepat daripada bahasa berbasis vektor. Tapi bukan itu intinya. Saya perlu menggunakan Python, karena saya memiliki sejumlah perpustakaan yang tidak tersedia dalam bahasa lain. Itu kendala saya. Saya perlu mengoptimalkan di dalamnya.

Dan saya tahu, bahwa banyak orang akan menyarankan paralelisasi, gpgpu dll. Tetapi saya ingin memaksimalkan kinerja single core terlebih dahulu, dan kemudian saya dapat memparalelkan kedua versi kode.

Terima kasih sebelumnya!

Ramanuj Lal
sumber
3
Cara yang berkaitan erat untuk memikirkan masalah ini: Haruskah Anda menggunakan struktur array (SoA) atau array struktur (AoS) untuk kinerja? Dengan SoA yang lebih mudah untuk membuat vektor dan AoS menjadi lebih ramah OOP di sebagian besar bahasa.
Patrick
ya @ Patrick, jika Anda melihat jawaban pertama, saya pikir Bart memberikan contoh praktis tentang poin yang Anda buat. Apakah saya benar? Saya perhatikan Anda mengatakan sebagian besar bahasa, jadi apakah ada bahasa yang keduanya kinerjanya hampir sama?
Ramanuj Lal
Algoritma + Struktur Data = Program oleh Niklaus Wirth
radarbob

Jawaban:

9

Seperti yang Anda lihat, cara OOP memberi saya banyak keamanan sehingga orang tidak akan menambahkan Volatilitas dengan cara yang salah, tetapi metode vektor sangat cepat gila! Apakah ada desain di mana saya bisa mendapatkan keduanya? Saya yakin banyak dari Anda telah mengalami pilihan desain yang serupa, bagaimana Anda mengatasinya?

Desain benda yang lebih besar. Sebuah Pixelobjek tidak memiliki ruang bernapas untuk loop paralel atau transformasi gambar GPU atau semacamnya. Dan Imageasalkan tidak harus melalui penghalang Pixelobjek kecil untuk mendapatkan data.


sumber
5

Ini adalah salah satu bidang di mana tidak mungkin untuk memberikan jawaban yang pasti, karena menyangkut pertukaran. Seperti yang Anda ketahui, baik OO, maupun berbasis vektor selalu unggul, tetapi semuanya tergantung pada bagaimana perangkat lunak akan digunakan.

Anda bisa mencoba untuk menggabungkan yang terbaik dari keduanya dan membuat Volatilityobjek dan VolatilitySeriesobjek, di mana yang kedua secara konseptual mewakili serangkaian objek Volatilitas, tetapi secara internal menggunakan metode penyimpanan yang jauh lebih cocok untuk vectorisasi perhitungan (struktur array) . Maka Anda hanya perlu mendidik pengguna Anda bahwa menggunakan VolatilitySeriesjauh lebih disukai Series(Volatility).

Bart van Ingen Schenau
sumber
Terima kasih Bart, itu ide yang bagus. Sebenarnya saya sudah seperti itu dalam desain saya saat ini di bagian-bagian, di mana beberapa objek seperti jumlah uang dirancang ulang seperti itu. Tetapi segera saya menyadari bahwa kode saya menjadi budak dari struktur data tertentu. Misalnya, jika saya memiliki VolatilitySeriesseperti yang Anda sarankan, maka saya tidak dapat memiliki list, atau a tupleatau (dengan asumsi Anda terbiasa dengan Python) DataFrameitem volatilitas. Itu mengganggu saya, karena arsitektur saya tidak skala dengan baik, dan manfaat memudar setelah beberapa saat. Dan itulah yang membawaku ke sini :).
Ramanuj Lal
Masalah lainnya adalah tidak ada yang menghentikan siapa pun untuk menulis kode seperti volatilitySeries[0] + 3.0, yang akan salah. Setelah Anda meronta-ronta nilai dari VolatilitySeries, Anda bisa mengamuk, sehingga keamanan hanya berumur pendek. Dalam lingkungan polimorfik di mana orang tidak selalu menyadari kelas yang tepat digunakan, ini sangat mungkin. Dan Anda tahu, Anda hanya bisa mendidik pengguna Anda begitu banyak. Saya tahu Anda akan mengatakan itu, hei saya juga bisa melakukan hal yang sama jika saya keluar Volatility.value, tetapi Anda tahu, setidaknya pengguna sekarang sadar bahwa dia menggunakan nilai khusus.
Ramanuj Lal
Beberapa mungkin juga menyarankan bahwa mengesampingkan semua fungsi biasa yang diwarisi dari Seriesdalam VolatilitySeries, tetapi itu mengalahkan seluruh tujuannya. Jadi apa yang saya pelajari dari menempuh jalan itu adalah bahwa memiliki VolatilitySeriesobjek hanya benar-benar berhasil dalam jangka panjang jika masing-masing sel bertipe Volatility.
Ramanuj Lal
@RamanujLal: Saya tidak tahu python cukup baik untuk menentukan apakah VolatileSeriespendekatan itu layak. Jika Anda sudah mencobanya dan tidak berhasil, maka Anda memiliki pilihan sulit untuk dibuat antara keamanan dan kecepatan. Kami tidak dapat membantu Anda di sana. (kecuali orang lain memiliki jawaban yang cemerlang)
Bart van Ingen Schenau