Penalti kinerja 20% untuk desain perangkat lunak yang bagus

17

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?

Daniel Shapero
sumber
Operasi matriks sparse mana yang Anda ukur?
Bill Barth
Perbanyak matriks-vektor. Matriks merentang dari . Saya membuat mereka grafik Laplacians untuk grafik acak Erdos-Renyi dengan derajat rata-rata d = log 2 n . Juga, angka 20% semakin buruk pada beberapa mesin, jadi sekarang saya lebih cenderung membuang semuanya. Mendesah dalamn=1024,...,16384d=catatan2n
Daniel Shapero
3
Bahasa pemrograman apa yang Anda gunakan? Biasanya sesuatu seperti C ++ akan membuat Anda lolos dengan desain elegan (ish) dengan biaya rendah (atau tidak ada). Dalam bahasa lain tanpa pemrograman meta (Java, Fortran, dll) biaya 20% tampaknya masuk akal.
LKlevin
Bisakah Anda menunjukkan kepada kami kode Anda? Bahasa apa yang Anda gunakan? Apa flag kompiler dan kompilasi? Apakah Anda menemukan secara tepat dari mana kinerja berasal? Bagaimana Anda memastikan Anda menemukan alasan yang tepat? Profiler apa yang Anda gunakan, dan bagaimana Anda menggunakannya? Apakah Anda yakin bahwa model objek yang bagus tidak diterapkan secara tidak efisien? 20% cukup kecil sehingga Anda perlu mengumpulkan banyak data dan memiliki analisis rinci sebelum mengatakan itu pasti karena desain, bukan, katakanlah, implementasi yang lebih rendah, atau beberapa masalah pengkodean lainnya.
Kirill
Catatan singkat: semua orang tampaknya memuji desain bagus di atas kinerja murni (tentu saja dengan alasan yang sangat valid). Tetapi, mengapa begitu banyak kode dunia nyata yang benar-benar tidak dapat dipertahankan? Apakah semua kode sembrono merasa bersalah dan karenanya diam di depan umum?
AlexE

Jawaban:

9

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:

  • Selesai dalam satu bulan
  • Berjalan dengan benar di laptop Anda dan beberapa workstation
  • Berjalan dengan efisien

Para ilmuwan secara bertahap lebih memperhatikan beberapa persyaratan umum lainnya dari rekayasa perangkat lunak:

  • Dokumentasi (Panduan pengguna, tutorial, komentar kode)
  • Maintainability (kontrol versi, pengujian, desain modular)
  • Dapat digunakan kembali (desain modular, "fleksibilitas")

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.

Aron Ahmadia
sumber
Saya ingin tahu tentang pembuat kode - saya pikir mereka mungkin berguna bagi saya tetapi saya khawatir mereka akan sulit untuk dipelihara. Saya tahu programmer Java sering menggunakannya tetapi mereka sering dirancang untuk menghasilkan kode untuk aplikasi tertentu. Apakah Anda tahu ada kode ilmiah yang menggunakannya?
Daniel Shapero
ATLAS, FFTW, Spiral, OSKI, Ignition, stencil_codegen, untuk beberapa nama. Ini tidak diiklankan secara publik, tetapi saya tidak akan terkejut jika beberapa kernel penting dalam MKL dan ESSL dihasilkan dengan cara ini. Menulis kode pembuatan kernel yang bisa dipelihara akan menjadi pertanyaan lanjutan yang menarik. Saya memiliki pengalaman dalam hal ini, tetapi saya tidak akan menganggap diri saya otoritas.
Aron Ahmadia
12

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.

Wolfgang Bangerth
sumber
Jawaban yang bagus, saya juga menambahkan pentingnya kinerja. Kode ilmiah yang diberikan tidak hanya melakukan perkalian matriks; jika 20% dari runtime Anda ada dalam perkalian matriks, kinerja 20% mencapai hanya ada perbedaan 4% secara keseluruhan, dan saya dengan senang hati akan mengambil itu dalam pertukaran untuk perpustakaan yang lebih mudah digunakan.
Aurelius
1
Dan pustaka tertulis yang lebih baik berarti lebih sedikit bug, sehingga Anda lebih sedikit waktu menunggu hasil yang salah.
Davidmh
4

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.

stali
sumber
1

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.

Mire
sumber
Saya tidak berpikir ini menjawab pertanyaan.
nicoguaro
0

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.

Jolvi
sumber