Sejauh mana generik dan meta-pemrograman menggunakan template C ++ bermanfaat dalam ilmu komputasi?

17

Bahasa C ++ menyediakan pemrograman generik dan metaprogramming melalui template. Teknik-teknik ini telah menemukan jalan mereka ke banyak paket komputasi ilmiah skala besar (misalnya, MPQC , LAMMPS , CGAL , Trilinos ). Tetapi apa yang sebenarnya mereka sumbangkan dalam komputasi ilmiah dalam nilai yang melampaui bahasa non-generik, non-meta seperti C atau Fortran dalam hal waktu pengembangan keseluruhan dan kegunaan untuk efisiensi yang sama atau memadai?

Mengingat tugas komputasi ilmiah, apakah pemrograman generik dan meta melalui templat C ++ menunjukkan peningkatan produktivitas, ekspresivitas, atau kegunaan yang diukur dengan tolok ukur yang dipahami dengan baik (garis kode, upaya orang, dll ...)? Sejalan dengan itu, risiko apa yang terkait dengan penggunaan templat C ++ untuk generik dan pemrograman?

Deathbreath
sumber
Saya khawatir pertanyaan ini bisa terlalu terbuka untuk pendapat, tetapi saya ingin melihat apa yang dikatakan orang di komunitas.
Geoff Oxberry
1
Saya benar-benar menghapus komentar yang gagal. Jika Anda ingin mem-posting ulang untuk chatting atau meta saya senang melakukannya. Lihat meta saya di sini .
Aron Ahmadia
3
Juga, lihat pertanyaan terkait di sini tentang saran kapan harus digunakan dan kapan harus menghindari templat ekspresi .
Aron Ahmadia
Saya tidak berpikir bahwa itu benar untuk mengatakan bahwa LAMMPS menggunakan template atau metaprogramming. LAMMPS adalah kode berorientasi objek yang terlihat sangat mirip dengan Fortran. Saya tidak berpikir MPQC memiliki banyak template, tetapi sangat berorientasi objek dan polimorfik.
Jeff
1
OpenFOAM banyak menggunakan template dan fitur C ++ lainnya.
Dohn Joe

Jawaban:

14

Saya pikir pada umumnya, metaprogramming template telah ditemukan tidak dapat digunakan dalam praktiknya - ini mengkompilasi terlalu lambat, dan pesan kesalahan yang kita dapatkan hanya mustahil untuk diuraikan. Hambatan masuk untuk pendatang baru juga terlalu tinggi saat menggunakan metaprogramming.

Tentu saja, pemrograman generik adalah masalah yang sama sekali berbeda, seperti yang disaksikan oleh Trilinos, kesepakatan.II (perpustakaan saya sendiri), DUNE, dan banyak perpustakaan lainnya - mengekspresikan konsep yang sama beroperasi pada tipe data yang berbeda adalah semacam no-brainer, dan sebagian besar masyarakat telah menerimanya selama masih dalam batas yang menghindari masalah metaprogramming. Saya pikir pemrograman generik memenuhi syarat sebagai keberhasilan yang jelas.

Tentu saja, tidak satu pun dari topik ini yang langsung terhubung ke OOP. OOP, sekali lagi, bisa saya katakan, diterima secara universal oleh komunitas komputasi ilmiah. Bahkan kurang dari pemrograman generik, ini bukan topik perdebatan: setiap perpustakaan yang berhasil ditulis dalam 15 tahun terakhir (apakah ditulis dalam C ++, C atau Fortran) menggunakan teknik OOP.

Wolfgang Bangerth
sumber
4
tmp mungkin sulit bagi pengguna pemula, tetapi sering dilakukan dengan sangat baik di dalam perpustakaan. Ini salah satu teknik yang benar-benar dapat mengurangi jumlah kode tetapi Anda benar-benar perlu tahu apa yang Anda lakukan. Jika Anda tidak percaya saya pergi membaca sumber Eigen atau Elemental. Kode cantiknya yang tanpa templat akan sangat mustahil.
aterrel
5
Tentu, ini adalah teknik dengan nilai. Tetapi sulit untuk mempertahankannya, dan sering kali sulit digunakan jika terpapar dengan antarmuka eksternal. Yang mengatakan, saya pikir salah satu alasan TMP belum cukup sukses yang mungkin diharapkan orang pada awalnya adalah bahwa kompiler menjadi sangat baik. TMP hidup dari kenyataan bahwa banyak hal yang diketahui pada waktu kompilasi, dan kemudian dapat disebarkan sebagai konstanta ke dalam kode aktual. Tetapi kompiler telah menjadi cukup baik dalam inlining, kloning fungsi, dll, sehingga sebagian besar manfaat hari ini dapat diperoleh dengan menggunakan pemrograman "normal".
Wolfgang Bangerth
15

Izinkan saya memberi contoh berdasarkan pengalaman. Sebagian besar perpustakaan yang saya gunakan dari hari ke hari menggunakan OOP dalam beberapa cara. OOP mampu menyembunyikan kompleksitas yang diperlukan untuk banyak domain, ini bukan mekanisme yang sangat membantu kinerja. Apa yang bisa terjadi adalah bahwa perpustakaan dapat menggunakan optimasi tertentu berdasarkan hirarki objek, tetapi sebagian besar adalah tentang menyembunyikan kompleksitas dari pengguna. Lihat Pola Desain, mereka adalah mekanisme yang sering digunakan untuk mencapai kompleksitas bersembunyi ini.

Ambil PETSc sebagai contoh. PETSc menggunakan model inspektur / pelaksana OOP di mana setiap algoritmanya melihat rutinitas yang tersedia di objek tertentu dan memilih yang akan dieksekusi untuk menyelesaikan rutin. Hal ini memungkinkan pengguna untuk memisahkan masalah, misalnya tindakan matriks dapat mencakup segala jenis rutin yang diblokir atau dioptimalkan dan secara efektif digunakan oleh banyak pemecah iteratif. Dengan memberikan pengguna kemampuan untuk menentukan tipe data dan evaluasi mereka sendiri, mereka mendapatkan beberapa rutinitas penting dan juga memiliki seluruh fungsi perpustakaan masih tersedia.

Contoh lain yang akan saya berikan adalah FEniCS dan deal.II. Kedua perpustakaan ini menggunakan OOP untuk menggeneralisasi sejumlah besar Metode Elemen Hingga. Dalam segala hal mulai dari jenis elemen, urutan elemen, representasi quadrature, dan sebagainya dapat dipertukarkan. Walaupun kedua pustaka ini "lebih lambat" daripada beberapa kode FEM terstruktur dengan tujuan khusus, mereka mampu menyelesaikan berbagai masalah dengan banyak kompleksitas FEM yang tidak diketahui pengguna.

Contoh terakhir saya adalah Elemental. Elemental adalah perpustakaan aljabar linear padat baru yang telah mengambil kesulitan mengelola komunikator MPI dan lokasi data ke konstruksi bahasa yang sangat sederhana. Hasilnya adalah bahwa jika Anda memiliki kode serial FLAME, dengan mengubah tipe data Anda juga dapat memiliki kode paralel melalui Elemental. Yang lebih menarik Anda bisa bermain dengan distribusi data dengan mengatur distribusi yang sama dengan yang lain.

OOP harus dianggap sebagai cara untuk mengelola kompleksitas, bukan paradigma untuk bersaing dengan perakitan linting tangan. Juga melakukannya dengan buruk akan menghasilkan banyak overhead sehingga seseorang harus menjaga waktu dan memperbarui mekanisme yang mereka gunakan.

aterrel
sumber
3

Apa fitur bahasa OOPlakukan untuk komputasi ilmiah adalah membuat pernyataan kode yang lebih kompak yang membantu dalam memahami dan menggunakan kode lebih baik. Sebagai contoh, FFTrutinitas perlu membawa sejumlah besar argumen untuk setiap panggilan fungsi membuat kode rumit.

Dengan menggunakan moduleatau classpernyataan hanya apa yang dibutuhkan pada saat panggilan dapat dilewati, karena sisa argumen berkaitan dengan pengaturan masalah (yaitu ukuran array, dan koefisien).

Dalam pengalaman saya, saya memiliki SUBROUTINEpanggilan dengan 55 argumen (masuk & keluar) dan saya mengurangi itu menjadi 5 membuat kode lebih baik.

Itu nilai.

Ja72
sumber
3

Saya seorang pendukung kuat pemrograman generik dan meta-pemrograman untuk komputasi ilmiah. Saya sebenarnya mengembangkan perpustakaan perangkat lunak C ++ gratis untuk metode Galerkin berdasarkan teknik yang disebut Feel ++ (http://www.feelpp.org) yang terus mendapatkan momentum. Benar bahwa masih ada kesulitan seperti waktu kompilasi yang lambat dan kurva belajar bisa curam jika seseorang ingin memahami apa yang terjadi di belakang layar. Namun ini sangat menarik dan mengejutkan. Jika dilakukan di tingkat pustaka dan menyembunyikan kompleksitas di balik bahasa khusus domain, Anda mendapatkan alat yang sangat kuat. Kami memiliki berbagai metode yang dapat kami gunakan dan bandingkan. Untuk tujuan pengajaran komputasi ilmiah ini luar biasa, untuk penelitian dan metode numerik baru juga, untuk aplikasi skala besar, baik kita mengerjakannya tapi sejauh ini bagus, kita sudah bisa melakukan beberapa hal yang bagus. Kami memiliki insinyur, fisikawan dan ahli matematika yang menggunakannya: kebanyakan dari mereka hanya menggunakan bahasa untuk formulasi variasi dan mereka senang dengan itu. Melihat beberapa formulasi yang dimanipulasi rekan fisikawan kita, saya tidak ingin melihat mereka dilakukan "dengan tangan" tanpa bahasa tingkat tinggi untuk menggambarkan formulasi variasional. Saya pribadi menganggap bahwa "teknik" atau "paradigma" ini sekarang diperlukan untuk mengatasi kompleksitas dalam kode komputasi ilmiah dengan harus mengalikan ukuran kode dengan faktor yang sangat besar. Mungkin ada kebutuhan untuk meningkatkan dukungan meta-pemrograman dalam C ++ tetapi sudah dalam kondisi yang baik terutama karena C ++ 11.

christophe Prud'homme
sumber
2

Anda mungkin menemukan makalah http://arxiv.org/abs/1104.1729 relevan dengan pertanyaan Anda. Ini membahas templat ekspresi (aplikasi tertentu dari meta-pemrograman templat yang digunakan dalam kode ilmiah) dari perspektif kinerja.

Juan M. Bello-Rivas
sumber
Makalah itu membuatku gila. Bandingkan dataran Fortran tercepat yang Anda miliki dengan MKL dan itu akan kalah juga. Perakitan yang disetel dengan tangan bukanlah sesuatu yang dicita-citakan, itu adalah apa yang Anda lakukan ketika setiap nanodetik berharga dan dapat digunakan kembali oleh banyak orang.
aterrel
@aterrel: Inilah kontras yang saya ingin tahu. Mengetahui bahwa Anda harus melakukan optimasi tangan sebagai tahap pengembangan terakhir, bahasa apa yang akan Anda pilih sebagai dasar untuk digunakan sebelum tahap terakhir? Apakah kita memiliki data keras untuk menyarankan bahasa mana yang harus dipilih?
Deathbreath
9
@ Deathbreath: Saya akan mengulangi jawaban yang saya buat di beberapa utas lainnya juga - bahwa pada umumnya, menyetel sedikit terakhir dari kode Anda adalah sesuatu yang sangat jarang Anda lakukan. Tetapi Anda memprogram algoritma tingkat tinggi sepanjang waktu. Jadi pilih bahasa yang memungkinkan Anda melakukan hal-hal besar dengan cepat. Selalu ada cara untuk memasukkan hal-hal tingkat rendah entah bagaimana, tetapi seharusnya tidak menjadi hal yang menentukan pilihan bahasa pemrograman Anda.
Wolfgang Bangerth
0

Template sangat bagus untuk menghapus pemeriksaan jenis / domain saat run-time. Ini dapat diurus pada saat kompilasi. Secara teori ini dapat meningkatkan kinerja dibandingkan dengan jenis implementasi yang sama di C atau Fortran di mana pengecekan tipe hanya dapat dilakukan pada saat run-time - pengecekan diterapkan dalam kode sumber. Namun, Anda dapat mencapai hasil yang sama dalam C menggunakan opsi precompiler tetapi ini harus dilakukan dengan tangan tidak seperti template.

Namun, templat dapat menghasilkan overhead yang signifikan juga. Mereka sering dapat membuat kode mengasapi yang dapat berdampak pada penggunaan cache instruksi. Lebih jauh lagi, pendekatan generik sering dapat membelenggu kompiler selama optimasi - tidak selalu mudah untuk analisis kode ketika menggunakan pendekatan generik. Selalu ada masalah dengan otomatisasi - termasuk optimisasi kompiler - sangat sering kode output tidak ramah cache.

Manfaat dari pengecekan jenis / domain, meskipun tentu saja lebih aman, adalah satu-satunya manfaat nyata yang dapat saya lihat dalam hal kinerja dan ini biasanya tidak terlihat. Tapi seperti yang saya katakan efek keseluruhan bisa negatif tergantung apa yang Anda lakukan. Itu sebabnya seringkali lebih baik untuk mengoptimalkan kode Anda secara manual di mana Anda mengalami hambatan yang signifikan.

cdcdcd
sumber