Cấu trúc dữ liệu cho mã khối hữu hạn: Mảng so với các lớp


11

Tôi phải viết mã âm lượng hữu hạn cho Magnetohydrodynamics (MHD). Tôi đã viết mã số trước đây nhưng không ở quy mô này. Tôi chỉ muốn hỏi cái nào sẽ là một lựa chọn tốt, sử dụng cấu trúc dữ liệu (cách tiếp cận hướng đối tượng) với các lớp hoặc chỉ sử dụng nhiều mảng cho các thuộc tính khác nhau, về tốc độ, khả năng mở rộng, v.v. Tôi dự định viết mã bằng python và sử dụng fortran cho phần chuyên sâu về số lượng.

Một ví dụ cho lớp trong python sẽ là

class Cell:
   def __init__(self, x, y, z, U):

Mảng có thể được định nghĩa đơn giản là

x[nx][ny][nz]
y[nx][ny][nz]
z[nx][ny][nz]
U[nx][ny][nz]

Vân vân.

Câu trả lời:


9

Câu trả lời đơn giản: trong python hiện đại, mỗi loại dữ liệu là một lớp, do đó, chính thức không có sự khác biệt giữa hai giải pháp bạn đề xuất. (Hãy nhớ sử dụng các lớp kiểu mới: các lớp cổ điển đã lỗi thời! Xem http://docs.python.org/2/reference/datamodel.html#new-style-and- classic-classes )

Bây giờ câu hỏi nên là: làm thế nào để tôi tổ chức một cấu trúc dữ liệu hiệu quả trong python? Không có nghi ngờ rằng chính ý tưởng tổ chức các tế bào như là một mảng của các class Celltrường hợp là quá kém hiệu quả. Bạn sẽ kết thúc với một mớ hỗn độn các con trỏ và dữ liệu không liên tục được sắp xếp như một danh sách liên kết phức tạp. Tất nhiên bạn có khả năng dễ dàng chèn các ô mới vào danh sách của mình: nhưng bạn có cần tính năng này không? Ngược lại, bạn sẽ có lưu trữ dữ liệu không liền kề và bạn phải truy cập vào mọi ô theo các mức độ khác nhau.

Nếu bạn sắp xếp dữ liệu của mình như một numpy.ndarraydữ liệu thì liền kề bộ nhớ và việc truy cập các ô khác nhau chỉ đơn giản là thực hiện sải bước qua khối bộ nhớ của bạn: không gian hiệu quả (không lãng phí bộ nhớ cho con trỏ) và nhanh chóng .

Như Ethan đã chỉ ra, các khái niệm OO nên được sử dụng, nhưng ở cấp độ cao hơn, một khi cấu trúc dữ liệu mức thấp hiệu quả đã được triển khai, thường là thông qua numpy.ndarray.

Lập trình OO có nghĩa là liên kết dữ liệu với các phương thức hoạt động trên chính dữ liệu ở mức độ trừu tượng cao hơn. (Một ví dụ: Tôi đã triển khai mã FEM trong đó ma trận độ cứng được định nghĩa là một lớp với phương pháp cho yếu tố cholesky siêu nốt thưa thớt. Việc triển khai đầu tiên là trong lõi: khi cần triển khai ngoài lõi, điều này là cần thiết đã thu được thông qua kế thừa và điều chỉnh tối thiểu cho việc lưu trữ dữ liệu gạch chân. Gần như 100% mã cholesky siêu nốt được sử dụng lại.)

Một nhận xét cuối cùng, nhưng rất quan trọng: một thủ tục số hiệu quả là kết quả của việc ánh xạ thông minh thuật toán và cấu trúc dữ liệu vào kiến ​​trúc điện toán mục tiêu của bạn. Nếu bạn bắt đầu với cấu trúc dữ liệu sai, không có cách nào phục hồi hiệu quả, mà không viết lại hoàn toàn.


@EthanCoon Cảm ơn bạn đã nhận xét của bạn cho câu trả lời khác, điều đó dẫn tôi viết một bài của riêng tôi.
Stefano M

10

Tôi đã suy nghĩ về điều này một vài ngày trước (cũng bằng Python). Cá nhân tôi không nghĩ rằng lập trình hướng đối tượng luôn phù hợp với lập trình số. Bạn có thể bị phân tâm với việc thiết kế các lớp thay vì chỉ giải các phương trình. Tôi thích ở lại với các hàm đơn giản, và với numpy bạn có thể có phương trình của bạn được véc tơ hóa nên số lượng dòng bạn cần là rất ít. Numpy khá nhanh vì các tính toán thực tế được thực hiện với phần cuối C (hoặc FORTRAN?).

Những gì tôi muốn khuyên bạn nên làm,

  1. Viết một kịch bản Python giải quyết phiên bản đơn giản nhất có thể của vấn đề của bạn bằng cách sử dụng phương pháp tiếp cận chức năng với numpy. Ví dụ: có mọi thứ trong đơn vị tùy ý và chỉ thử 1D (hoặc 2D). Nó là hoàn toàn tốt ở giai đoạn này nếu mã lộn xộn. Điều quan trọng là bạn đang tiến về phía trước với dự án của bạn.
  2. Một khi bạn có một cái gì đó hoạt động. Xác định nơi mã là dài dòng và khúc xạ. Ở giai đoạn này, bạn có thể chơi xung quanh với các ý tưởng khác nhau về cách đơn giản hóa mã của bạn. Có thể giới thiệu các chức năng mà bạn nhận thấy bạn đang lặp lại chính mình. Bạn có thể so sánh với phiên bản gốc để bạn biết rằng bạn không giới thiệu lỗi.
  3. Quyết định xem cách tiếp cận hướng đối tượng sẽ làm giảm độ phức tạp của mã hơn nữa.

Thông điệp chính là không bắt đầu viết các lớp cho đến khi bạn đã giải quyết vấn đề theo cách đơn giản nhất có thể. Chỉ bằng cách đạt được kinh nghiệm giải quyết vấn đề, bạn sẽ biết cách xác định giao diện hướng đối tượng của mình. Nếu bạn làm điều này trước khi ra tay, nó có khả năng chỉ cản trở bạn.


3
Tôi không đồng ý mạnh mẽ với tuyên bố rằng OO không phù hợp với lập trình số, nhưng nơi phù hợp thì ở mức cao hơn nhiều. OO rất hữu ích cho những thứ như mô hình vật lý, mắt lưới, bộ giải, v.v., nhưng hầu như luôn không phù hợp ở cấp độ tế bào.
Ethan Coon

Trong bài đăng tôi muốn cảnh báo về sự sụp đổ tiềm năng của "sự khách quan hóa sớm" của mã số, đặc biệt là khi một người đang bắt đầu. Tôi không bất lợi khi sử dụng các đối tượng, xem điểm thứ ba của tôi: nếu các đối tượng có thể giảm độ phức tạp thì chúng là một ý tưởng tốt. Tôi đồng ý rằng các ví dụ bạn trích dẫn là sử dụng tốt, nhưng đến thời điểm đó đòi hỏi kinh nghiệm.
boyfarrell
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.