Saya sedang menulis perpustakaan kecil untuk perhitungan matriks jarang sebagai cara untuk belajar sendiri untuk memanfaatkan pemrograman berorientasi objek. Saya telah bekerja sangat keras untuk memiliki model objek yang bagus, di mana bagian-bagiannya (matriks jarang dan grafik yang menggambarkan struktur konektivitas mereka) sangat longgar digabungkan. Dalam pandangan saya sendiri, kode ini jauh lebih mudah dikembangkan dan dipelihara untuk itu.
Namun, ini juga agak lambat dibandingkan jika saya menggunakan pendekatan tumpul. Untuk menguji pengorbanan memiliki model objek ini, saya menulis tipe matriks baru yang memecah enkapsulasi grafik yang mendasari untuk melihat seberapa cepat itu akan berjalan.
Pada awalnya, itu tampak sangat suram; kode yang pernah saya banggakan berlari 60% lebih lambat dari versi tanpa desain perangkat lunak yang elegan. Tapi, saya bisa membuat beberapa optimasi tingkat rendah - sebaris fungsi dan mengubah sedikit lingkaran - tanpa mengubah API sama sekali. Dengan perubahan itu, sekarang hanya 20% lebih lambat dari kompetisi.
Yang membawa saya ke pertanyaan saya: Berapa banyak kehilangan kinerja yang harus saya terima jika itu berarti saya memiliki model objek yang bagus?
sumber
Jawaban:
Sangat sedikit pengembang perangkat lunak ilmiah yang memahami prinsip-prinsip desain yang baik, jadi saya minta maaf jika jawaban ini agak bertele-tele. Dari perspektif rekayasa perangkat lunak, tujuan pengembang perangkat lunak ilmiah adalah untuk merancang solusi yang memuaskan serangkaian kendala yang sering saling bertentangan .
Berikut adalah beberapa contoh khas dari kendala ini, seperti yang mungkin diterapkan pada desain perpustakaan matriks jarang Anda:
Para ilmuwan secara bertahap lebih memperhatikan beberapa persyaratan umum lainnya dari rekayasa perangkat lunak:
Anda mungkin memerlukan lebih atau kurang satu dari persyaratan ini. Jika Anda mencoba untuk memenangkan hadiah Gordon Bell untuk kinerja, maka bahkan sebagian kecil dari persentase itu relevan, dan beberapa hakim akan mengevaluasi kualitas kode Anda (selama Anda dapat meyakinkan mereka itu benar). Jika Anda mencoba untuk membenarkan menjalankan kode ini pada sumber daya bersama seperti cluster atau superkomputer, sering kali Anda harus mempertahankan klaim tentang kinerja kode Anda, tetapi ini jarang sangat ketat. Jika Anda mencoba untuk mempublikasikan makalah dalam jurnal yang menggambarkan perolehan kinerja dari pendekatan Anda, maka Anda harus secara sah menjadi lebih cepat daripada pesaing Anda, dan 20% kinerja merupakan trade-off yang dengan senang hati saya akan buat untuk pemeliharaan dan penggunaan kembali yang lebih baik.
Kembali ke pertanyaan Anda, "desain yang bagus", diberikan waktu pengembangan yang cukup, seharusnya tidak pernah mengorbankan kinerja. Jika tujuannya adalah untuk membuat kode yang berjalan secepat mungkin, maka kode tersebut harus dirancang di sekitar kendala tersebut. Anda dapat menggunakan teknik seperti pembuatan kode, perakitan inline, atau memanfaatkan perpustakaan yang sangat disetel untuk membantu Anda memecahkan masalah Anda.
Tetapi bagaimana jika Anda tidak memiliki waktu pengembangan yang cukup? Apa yang cukup bagus? Yah, itu tergantung, dan tidak ada yang akan bisa memberi Anda jawaban yang baik untuk pertanyaan ini tanpa lebih banyak konteks.
FWIW: Jika Anda benar-benar tertarik untuk menulis kernel matriks jarang berkinerja tinggi, Anda harus membandingkan dengan instalasi PETSc yang dioptimalkan dan bekerja dengan tim mereka jika Anda mengalahkannya, mereka akan dengan senang hati memasukkan kernel yang sudah disetel ke perpustakaan.
sumber
Ini pertanyaan tentang apa yang Anda habiskan. Bagi sebagian besar dari kita, kita menghabiskan 3/4 dari waktu pemrograman dan 1/4 dari waktu menunggu hasil. (Angka Anda mungkin berbeda, tetapi saya pikir angka itu tidak sepenuhnya tanpa nilai.) Jadi, jika Anda memiliki desain yang memungkinkan Anda untuk memprogram dua kali lebih cepat (3/4 unit waktu daripada 1,5 unit waktu), maka Anda dapat mengambil 300% hit dalam kinerja (dari unit 1/4 hingga 1 kali) dan Anda masih unggul dalam hal waktu nyata yang dihabiskan untuk memecahkan masalah.
Di sisi lain, jika Anda melakukan perhitungan tugas berat, perhitungan Anda mungkin terlihat berbeda dan Anda mungkin ingin menghabiskan lebih banyak waktu untuk mengoptimalkan kode Anda.
Bagi saya, 20% tampaknya merupakan pertukaran yang cukup baik jika Anda akhirnya menjadi lebih produktif.
sumber
IMHO penalti hingga 50% (karena alasan apa pun) tidak terlalu buruk.
Sebenarnya saya telah melihat perbedaan 0-30% dalam kinerja hanya berdasarkan pada jenis kompiler. Ini untuk rutinitas MatMult PETSc yang jarang pada matriks yang timbul dari diskritisasi FE tingkat rendah.
sumber
Desain perangkat lunak tidak akan secara otomatis meningkat seiring waktu. Performa akan. Anda akan mendapatkan 20% kembali dengan CPU Anda berikutnya. Selain itu, desain perangkat lunak yang baik akan memudahkan untuk memperluas atau meningkatkan perpustakaan di masa mendatang.
sumber
Prinsip umum adalah memilih desain yang baik terlebih dahulu dan kemudian mengoptimalkan kinerja hanya jika diperlukan . Kasus penggunaan di mana perolehan kinerja 20% benar-benar dibutuhkan cenderung agak jarang, jika muncul sama sekali.
sumber