Hướng đối tượng và lập trình dựa trên vector


14

Tôi bị giằng xé giữa thiết kế hướng đối tượng và vector. Tôi yêu các khả năng, cấu trúc và sự an toàn mà các đối tượng mang lại cho toàn bộ kiến ​​trúc. Nhưng đồng thời, tốc độ rất quan trọng đối với tôi và việc có các biến float đơn giản trong một mảng thực sự giúp ích cho các ngôn ngữ / thư viện dựa trên vectơ như Matlab hoặc numpy trong Python.

Đây là một đoạn mã tôi đã viết để minh họa quan điểm của mình

Vấn đề: Thêm số biến động Tow. Nếu x và y là hai số biến động, tổng của độ biến động là (x ^ 2 + y ^ 2) ^ 0,5 (giả sử điều kiện toán học nhất định nhưng điều đó không quan trọng ở đây).

Tôi muốn thực hiện thao tác này rất nhanh, đồng thời tôi cần đảm bảo rằng mọi người không chỉ thêm biến động sai cách (x + y). Cả hai điều này đều quan trọng.

Thiết kế dựa trên OO sẽ giống như thế nà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))

(Ngoài ra: Đối với những người mới sử dụng Python, __add__chỉ là một chức năng ghi đè +toán tử)

Giả sử tôi thêm danh sách kéo các giá trị biến động

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

(Ngoài ra: Một lần nữa, Sê-ri trong Python là một danh sách có chỉ mục) Bây giờ tôi muốn thêm hai:

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

Chỉ cần phần bổ sung chạy trong 3,8 giây trên máy của tôi, kết quả tôi đã đưa ra không bao gồm thời gian khởi tạo đối tượng, chỉ có mã bổ sung đã được tính thời gian. Nếu tôi chạy điều tương tự bằng cách sử dụng mảng 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

Nó chạy trong 0,03 giây. Điều đó nhanh hơn gấp 100 lần!

Như bạn có thể thấy, cách OOP mang lại cho tôi rất nhiều sự bảo mật mà mọi người sẽ không thêm Biến động sai cách, nhưng phương pháp vectơ thì quá nhanh! Có một thiết kế trong đó tôi có thể nhận được cả hai? Tôi chắc chắn rất nhiều bạn đã chạy vào các lựa chọn thiết kế tương tự, làm thế nào bạn tìm ra nó?

Sự lựa chọn ngôn ngữ ở đây là không quan trọng. Tôi biết nhiều bạn sẽ khuyên rằng nên sử dụng C ++ hoặc Java và mã có thể chạy nhanh hơn các ngôn ngữ dựa trên vector. Nhưng đó không phải là vấn đề. Tôi cần sử dụng Python, vì tôi có một loạt các thư viện không có sẵn bằng các ngôn ngữ khác. Đó là hạn chế của tôi. Tôi cần phải tối ưu hóa trong đó.

Và tôi biết rằng, rất nhiều người sẽ đề xuất song song hóa, gpgpu, v.v. Nhưng tôi muốn tối đa hóa hiệu suất lõi đơn trước, và sau đó tôi có thể song song cả hai phiên bản mã.

Cảm ơn trước!


3
Một cách liên quan chặt chẽ để suy nghĩ về vấn đề này: Bạn nên sử dụng cấu trúc của mảng (SoA) hay một mảng cấu trúc (AoS) cho hiệu suất? Với SoA dễ dàng hơn để vector hóa và AoS thân thiện hơn với hầu hết các ngôn ngữ.
Patrick

vâng @Patrick, nếu bạn thấy câu trả lời đầu tiên, tôi nghĩ Bart đã đưa ra một ví dụ thực tế về điểm bạn đang thực hiện. Tôi có đúng không Tôi nhận thấy bạn nói hầu hết các ngôn ngữ, vậy có ngôn ngữ nào mà cả hai đều gần nhau về hiệu suất không?
Ramanuj Lal

Câu trả lời:


9

Như bạn có thể thấy, cách OOP mang lại cho tôi rất nhiều sự bảo mật mà mọi người sẽ không thêm Biến động sai cách, nhưng phương pháp vectơ thì quá nhanh! Có một thiết kế trong đó tôi có thể nhận được cả hai? Tôi chắc chắn rất nhiều bạn đã chạy vào các lựa chọn thiết kế tương tự, làm thế nào bạn tìm ra nó?

Thiết kế các đối tượng lớn hơn. Một Pixelđối tượng không có phòng thở cho một vòng lặp song song hoặc biến đổi hình ảnh GPU hoặc bất cứ thứ gì tương tự. An Imagekhông cung cấp nó không phải đi qua hàng rào của một Pixelđối tượng tuổi teen để lấy dữ liệu.


5

Đây là một trong những lĩnh vực không thể đưa ra câu trả lời dứt khoát, bởi vì nó liên quan đến sự đánh đổi. Như bạn đã tìm ra, cả OO và vector đều không vượt trội, nhưng tất cả phụ thuộc vào cách phần mềm sẽ được sử dụng.

Bạn có thể cố gắng kết hợp tốt nhất cả hai và tạo cả Volatilityđối tượng và VolatilitySeriesđối tượng, trong đó khái niệm thứ hai đại diện cho một loạt các đối tượng Biến động, nhưng bên trong sử dụng một phương thức lưu trữ phù hợp hơn nhiều cho việc tính toán các phép tính (cấu trúc của mảng) . Sau đó, bạn chỉ cần giáo dục người dùng của bạn rằng sử dụng VolatilitySerieslà tốt hơn nhiều Series(Volatility).


Cảm ơn Bart, đó là một ý tưởng tốt. Trong thực tế, tôi đã đi theo cách đó trong thiết kế hiện tại của mình ở các bộ phận, nơi một số đối tượng như số tiền được thiết kế lại theo cách đó. Nhưng ngay sau đó tôi nhận ra rằng mã của tôi trở thành nô lệ của cấu trúc dữ liệu cụ thể đó. Ví dụ: Nếu tôi có một VolatilitySeriesnhư bạn đề xuất, thì tôi không thể có listmột tuplehoặc (hoặc giả sử bạn đã quen thuộc với Python) một DataFramemục biến động. Điều đó làm phiền tôi, bởi vì sau đó kiến ​​trúc của tôi không có quy mô tốt, và lợi ích sẽ mất dần sau một thời gian. Và đó là những gì mang tôi đến đây :).
Ramanuj Lal

Vấn đề khác là không có gì ngăn cản bất cứ ai viết mã như thế volatilitySeries[0] + 3.0, điều này sẽ sai. Khi bạn luồn lách các giá trị từ đó VolatilitySeries, bạn có thể trở nên điên loạn, vì vậy sự an toàn chỉ tồn tại trong thời gian ngắn. Trong một môi trường đa hình, nơi mọi người không phải lúc nào cũng nhận thức được lớp chính xác đang được sử dụng, điều này rất có thể. Và bạn biết đấy, bạn chỉ có thể giáo dục người dùng của mình rất nhiều. Tôi biết bạn sẽ nói rằng, tôi cũng có thể làm điều tương tự nếu tôi luồn lách ra ngoài Volatility.value, nhưng bạn biết đấy, ít nhất người dùng nhận thức được rằng anh ta đang sử dụng một giá trị đặc biệt.
Ramanuj Lal

Một số cũng có thể đề xuất rằng ghi đè tất cả các chức năng thông thường được kế thừa từ Seriestrong VolatilitySeries, nhưng điều đó đánh bại toàn bộ mục đích. Vì vậy, những gì tôi đã học được từ việc đi xuống con đường đó là việc có một VolatilitySeriesđối tượng chỉ thực sự hoạt động trong thời gian dài nếu các ô riêng lẻ thuộc loại Volatility.
Ramanuj Lal

@RamanujLal: Tôi không biết rõ về trăn đủ để xác định xem VolatileSeriesphương pháp này có khả thi hay không. Nếu bạn đã thử nó và nó không hoạt động, thì bạn có một lựa chọn khó khăn để thực hiện giữa an toàn và tốc độ. Chúng tôi không thể giúp bạn ở đó. (trừ khi người khác có câu trả lời xuất sắc)
Bart van Ingen Schenau
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.