Struktur data untuk kode volume terbatas: Array vs Kelas

11

Saya harus menulis kode volume terbatas untuk Magnetohydrodynamics (MHD). Saya telah menulis kode numerik sebelumnya tetapi tidak pada skala ini. Saya hanya ingin bertanya yang akan menjadi pilihan yang baik, menggunakan struktur data (pendekatan berorientasi objek) dengan kelas atau hanya menggunakan beberapa array untuk properti yang berbeda, dalam hal kecepatan, skalabilitas dll. Saya berencana untuk menulis kode dengan python, dan gunakan fortran untuk bagian intensif numerik.

Contoh untuk kelas dalam python adalah

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

Array dapat didefinisikan sebagai

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

dll.

Maverick
sumber

Jawaban:

9

Jawaban sederhana: dalam python modern setiap tipe data adalah kelas, jadi secara formal tidak ada perbedaan antara dua solusi yang Anda usulkan. (Harap ingat untuk menggunakan kelas gaya baru: kelas klasik sudah usang! Lihat http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes )

Sekarang pertanyaannya seharusnya: bagaimana cara mengatur struktur data yang efisien dalam python? Tidak ada keraguan bahwa gagasan untuk mengatur sel-sel sebagai serangkaian class Cellcontoh terlalu tidak efisien. Anda akan berakhir dengan kekacauan petunjuk dan data tidak darurat yang disusun seperti daftar tertaut yang rumit. Anda tentu saja memiliki kemampuan untuk dengan mudah memasukkan sel-sel baru dalam daftar Anda: tetapi apakah Anda memerlukan fitur ini? Sebaliknya Anda akan memiliki penyimpanan data yang tidak bersebelahan, dan Anda harus mengakses setiap sel dengan berbagai tingkat tipuan.

Jika Anda mengatur data Anda sebagai data numpy.ndarraymaka memori-berdekatan, dan mengakses sel yang berbeda cukup dilakukan melangkah melalui blok memori Anda: ruang efisien (tidak ada memori yang terbuang untuk pointer) dan cepat .

Seperti yang ditunjukkan oleh Ethan, konsep OO harus digunakan, tetapi pada tingkat yang lebih tinggi, setelah struktur data tingkat rendah yang efisien telah diimplementasikan, biasanya melalui numpy.ndarray.

Pemrograman OO berarti mengikat data ke metode yang beroperasi pada data itu sendiri pada tingkat abstraksi yang lebih tinggi. (Contoh: Saya menerapkan kode FEM di mana matriks kekakuan didefinisikan sebagai kelas dengan metode untuk faktorisasi cholesky super-nodal yang jarang. Implementasi pertama adalah dalam-inti: ketika implementasi di luar-inti diperlukan, ini diperoleh melalui pewarisan dan penyesuaian minimal pada penyimpanan data yang digarisbawahi. Hampir 100% dari kode cholesky super-nodal digunakan kembali.)

Komentar terakhir, tetapi penting: prosedur numerik yang efisien adalah hasil dari pemetaan cerdas suatu algoritma dan struktur data ke arsitektur komputasi target Anda. Jika Anda mulai dengan struktur data yang salah, tidak ada cara untuk memulihkan efisiensi, tanpa penulisan ulang yang lengkap.

Stefano M
sumber
@EthanCoon Terima kasih atas komentar Anda untuk jawaban yang lain, yang membuat saya menulis sendiri.
Stefano M
10

Saya merenungkan ini beberapa hari yang lalu (juga dengan Python). Secara pribadi saya tidak berpikir bahwa pemrograman berorientasi objek selalu cocok untuk pemrograman numerik. Anda bisa terganggu dengan mendesain kelas daripada hanya menyelesaikan persamaan. Saya lebih suka tetap dengan fungsi sederhana, dan dengan numpy Anda dapat memiliki persamaan Anda vektor jadi jumlah baris yang Anda butuhkan sangat sedikit. Numpy cukup cepat karena perhitungan yang sebenarnya dilakukan dengan ujung belakang C (atau FORTRAN?).

Apa yang saya sarankan Anda lakukan,

  1. Tulis skrip Python yang memecahkan versi paling sederhana dari masalah Anda menggunakan pendekatan fungsional dengan numpy. Misalnya, miliki semuanya dalam unit arbitrer dan coba 1D (atau 2D) saja. Tidak apa-apa pada tahap ini jika kodenya berantakan. Yang penting adalah Anda bergerak maju dengan proyek Anda.
  2. Setelah Anda memiliki sesuatu yang berfungsi. Identifikasi di mana kode itu bertulang belakang dan refraktor. Pada tahap ini Anda dapat bermain-main dengan berbagai ide tentang cara menyederhanakan kode Anda. Mungkin memperkenalkan fungsi-fungsi di mana Anda melihat Anda mengulangi diri Anda sendiri. Anda dapat membandingkan dengan versi aslinya sehingga Anda tahu bahwa Anda tidak memperkenalkan bug.
  3. Putuskan apakah pendekatan berorientasi objek akan mengurangi kompleksitas kode lebih lanjut.

Pesan utamanya adalah jangan mulai menulis kelas sampai Anda telah menyelesaikan masalah dengan cara yang sesederhana mungkin. Hanya dengan mendapatkan pengalaman memecahkan masalah, Anda akan tahu cara mendefinisikan antarmuka berorientasi objek. Jika Anda melakukan ini sebelumnya, kemungkinan besar hanya akan menghalangi.

Boyfarrell
sumber
3
Saya sangat tidak setuju dengan pernyataan bahwa OO tidak cocok untuk pemrograman numerik, tetapi di mana itu cocok adalah pada tingkat yang jauh lebih tinggi. OO sangat berguna untuk hal-hal seperti model fisika, jerat, pemecah, dll, tetapi hampir selalu tidak sesuai pada tingkat sel.
Ethan Coon
Dalam posting ini saya ingin memperingatkan tentang kemungkinan jatuhnya "objektifikasi prematur" kode numerik, terutama ketika seseorang memulai. Saya tidak suka menggunakan objek, lihat poin ketiga saya: jika objek dapat mengurangi kompleksitas maka mereka adalah ide yang bagus. Saya setuju bahwa contoh yang Anda sebutkan adalah kegunaan yang baik, tetapi untuk sampai ke titik itu membutuhkan pengalaman.
boyfarrell