Mengapa saya harus peduli dengan kinerja dan efisiensi mikro?

71

Banyak pertanyaan dan jawaban pada halaman C / C ++, secara khusus atau tidak langsung membahas masalah kinerja mikro (seperti overhead dari fungsi tidak langsung vs langsung vs inline), atau menggunakan algoritma O (N 2 ) vs O (N log N) pada daftar 100 item.

Saya selalu kode tanpa perhatian tentang kinerja mikro, dan sedikit perhatian tentang kinerja makro, fokus pada kode yang mudah dipelihara, dapat diandalkan, kecuali atau sampai saya tahu saya memiliki masalah.

Pertanyaan saya adalah mengapa sejumlah besar programmer begitu peduli? Apakah ini benar-benar masalah bagi sebagian besar pengembang, apakah saya hanya cukup beruntung untuk tidak perlu terlalu khawatir tentang hal itu, atau apakah saya seorang programmer yang buruk?

Tim Post
sumber
5
+1, pertanyaan umum yang bagus.
iammilind
+1 pertanyaan bagus..Saya menambahkan 2 tag .. harap Anda tidak keberatan tentang itu.
2
Saya kutip dua kutipan hebat 1) "Optimasi Prematur adalah akar dari semua kejahatan." 2) 80% dari waktu Anda akan dihabiskan sebesar 20% dari kode Anda (aturan 80/20).
James Khoury
2
Saya melihat beberapa jawaban berbicara tentang contoh O (n * n) saya. Saya secara eksplisit menentukan daftar 100 item, namun mereka tetap bersikeras bahwa O (nlogn) lebih baik, secara eksplisit menyatakan peningkatan kinerja jika daftar, pada masa depan, pergi ke 1000 atau juta. Apakah obsesi optimasi mikro ini karena pemrogram memprogram untuk kemungkinan persyaratan di masa depan dan persyaratan aktual aktual? (Di mana saya mendengar itu sebelumnya ...)
mattnz
5
@ James, kutipan penuh dari Donald Knuth adalah "Kita harus melupakan efisiensi kecil, katakanlah sekitar 97% dari waktu: optimasi prematur adalah akar dari semua kejahatan". Akan ada beberapa jawaban bagus tentang 3% sisanya di utas ini.
StuperUser

Jawaban:

14

Dalam praktiknya, kinerja jarang merupakan masalah yang perlu dikelola pada tingkat perincian itu. Sebaiknya perhatikan situasi jika Anda tahu Anda akan menyimpan dan memanipulasi data dalam jumlah besar, tetapi sebaliknya, Anda benar, dan lebih baik, menjaga hal-hal sederhana.

Salah satu perangkap termudah untuk jatuh ke dalam - terutama di C dan C ++ di mana Anda memiliki kontrol berbutir halus - adalah mengoptimalkan terlalu dini, dan pada tingkat yang terlalu halus. Secara umum aturannya adalah: A) jangan optimalkan sampai Anda tahu Anda memiliki masalah, dan B) jangan mengoptimalkan apa pun yang Anda belum terbukti sebagai area masalah dengan menggunakan profiler.

Sebuah konsekuensi wajar untuk B) adalah: programmer terkenal buruk dalam memprediksi di mana kemacetan kinerja mereka, meskipun, untuk satu, mereka pikir mereka baik dalam hal itu. Gunakan profiler, dan optimalkan bagian-bagian yang lambat, atau ubah algoritme jika satu bagian kode terlalu sering dipanggil, sehingga menyebabkan masalah.

jwismar
sumber
6
Yang lain: kode inisialisasi yang dijalankan sekali umumnya tidak perlu optimasi, jadi lihat di tempat lain.
Mike DeSimone
3
Tergantung seberapa sering "satu kali" itu. Ketika menjalankan ./configure, saya berani mengatakan hingga 75% dari waktu berjalan mungkin dihabiskan untuk kode "inisialisasi" dalam program yang dijalankan skrip. 25-50% bahkan mungkin dihabiskan untuk menghubungkan dinamis.
R ..
12
Aturan A adalah aturan yang mengerikan. Arsitektur suatu sistem memainkan peran dalam kinerja, dan jika Anda mengetahui kemudian arsitektur Anda tidak dapat mendukung persyaratan kinerja Anda, Anda pada dasarnya kacau. Jadi, sementara Anda bisa melewati detail yang bagus, mengabaikan sepenuhnya hal ini pada awalnya adalah hal yang salah.
edA-qa mort-ora-y
3
@ edA-qa: Dulu saya berpikir begitu, tetapi selama bertahun-tahun telah mengalami banyak proyek yang gagal atau gagal sebelum pertimbangan kinerja menjadi keprihatinan. Setiap kali saya memiliki masalah kinerja, perbaikannya adalah biaya yang relatif rendah, berhari-hari atau beberapa minggu, Tidak ada yang lebih memprihatinkan daripada "bug" lainnya yang mendeteksi perbaikan dalam pengembangan. Namun, hanya seperti item risiko lainnya, kinerja conere perlu diidentifikasi dan dimitigasi awal dalam proyek.
mattnz
5
OP bertanya mengapa begitu peduli, dan saya gagal melihat bagaimana tanggapan ini benar-benar menjawab pertanyaan, kecuali OP lebih tertarik mendengar seseorang berkata "jangan khawatir tentang itu!".
red-dirt
54

Saya pikir semua yang ada di daftar Anda adalah optimasi mikro, yang seharusnya tidak dilihat secara umum, kecuali untuk

menggunakan algoritma O (n * n) vs O (NlogN) pada daftar 100 item

yang saya pikir harus dilihat. Tentu, daftar itu adalah 100 item sekarang, dan semuanya cepat untuk n kecil , tapi saya akan segera bertaruh bahwa kode yang sama akan digunakan kembali untuk beberapa juta daftar baris, dan kode itu masih akan memiliki untuk bekerja secara wajar.

Memilih algoritma yang tepat tidak pernah merupakan optimasi mikro. Anda tidak pernah tahu jenis data apa yang kode yang akan digunakan untuk dua bulan atau dua tahun kemudian. Berbeda dengan "mikro-optimasi" yang mudah diterapkan dengan bimbingan profiler, perubahan algoritma sering membutuhkan desain ulang yang signifikan untuk memanfaatkan algoritma baru secara efektif. (Misalnya beberapa algoritma mengharuskan input data diurutkan, yang mungkin memaksa Anda untuk memodifikasi bagian signifikan dari aplikasi Anda untuk memastikan data tetap diurutkan)

Billy ONeal
sumber
36
+1 untuk "Memilih algoritme yang tepat tidak pernah merupakan optimasi mikro."
9
Saya memberi +1 juga, tetapi perhatikan bahwa memilih algoritma big-O-optimal ketika ukuran data Anda pasti kecil dapat merusak waktu pengembangan, ukuran program, dan mungkin bahkan penggunaan memori. Jika Anda menyortir tangan poker, apakah Anda benar-benar ingin menulis quicksort, smoothsort, atau mergesort? Saya akan mulai dengan semacam penyisipan sederhana atau menggunakan jaringan penyortiran.
R ..
8
Itu lucu. Dalam utas tentang mikro-optimasi, banyak komentator mengoptimalkan-mikro jawaban. ;)
Aman
5
"Saya akan segera bertaruh bahwa kode yang sama akan digunakan kembali untuk beberapa juta daftar baris": Itu sepenuhnya tergantung pada domain masalah. Contoh: jika Anda menulis algoritma catur, Anda dapat memastikan ukuran papan tidak akan berubah. Jika Anda program kendaraan otonom, jumlah roda tidak akan tumbuh yang cepat, baik.
nikie
3
Saya tidak suka "memilih algoritma yang tepat tidak pernah merupakan optimasi mikro" karena itu BENAR-BENAR benar, mengingat sifat dari kata "benar". Namun, saya merasa implikasi Anda benar-benar "paling cepat atau paling efisien" algoritma, yang saya tidak setuju. Memilih algoritma yang paling efisien adalah pilihan yang salah jika membutuhkan banyak waktu untuk mengimplementasikan dan kecepatan atau ruang segmen itu tidak menjadi masalah.
Casey Patton
18

Beberapa waktu yang lalu, di pekerjaan pertama saya, saya menulis kode untuk embedded system. Sistem ini menggunakan mikroprosesor 8086, dan memiliki memori terbatas. Kami menggunakan kompiler Intel C. Satu sistem yang saya bangun diperlukan untuk mengakses susunan struktur 3-d. Saya membangunnya persis seperti yang dikatakan buku itu kepada saya: panggil malloc untuk 3 dimensi, lalu alokasikan baris untuk dimensi berikutnya, lalu calloc untuk simpul akhir.

Itu cukup rumit (bagi saya pada saat itu), saya harus melakukan fitting curve, kontrol proses ANOVA dan analisis Chi-squared. Tidak ada perpustakaan yang melakukan ini untuk kami; kami harus menulis semuanya dan memasukkan semuanya ke 8086.

Sistem berjalan seperti anjing. Setelah profiling cepat, saya menemukan bahwa salah satu masalah terbesar adalah pengalokasi. Untuk memperbaiki masalah, saya meninggalkan semua panggilan ke malloc dan melakukan manajemen memori saya sendiri dari satu blok besar memori.


Dalam kasus lain pada pekerjaan yang sama, pelanggan mengeluh tentang waktu respons pada sistem kontrol proses statistik mereka. Tim sebelum saya telah merancang sistem "perangkat lunak PLC" di mana operator dapat menggunakan logika boolean untuk menggabungkan sinyal dan tripping switch. Mereka menulisnya dalam bahasa yang disederhanakan, apa yang kita sebut "bahasa spesifik domain" hari ini. seingat saya itu tampak seperti ((A1 + B1) > 4) AND (C1 > C2)dan sebagainya.

Desain asli mengurai dan menafsirkan string itu setiap kali dievaluasi. Pada prosesor kami yang sangat sedikit, ini menghabiskan banyak waktu, dan itu berarti pengontrol proses tidak dapat memperbarui secepat proses sedang berjalan.

Saya mengambil pandangan baru dan memutuskan bahwa saya bisa menerjemahkan logika itu menjadi kode assembly, saat runtime. Saya menguraikannya sekali dan kemudian setiap kali dijalankan, aplikasi memanggil fungsi yang dihasilkan secara dinamis. Agak seperti beberapa virus lakukan hari ini, saya kira (tapi saya tidak; benar-benar tahu). Hasilnya adalah peningkatan kinerja 100 kali lipat, yang membuat pelanggan dan bos saya benar-benar bahagia.

Kode baru hampir tidak dapat dipelihara, karena saya telah membangun kompiler kustom . Tetapi keunggulan kinerja jauh melebihi kerugian pemeliharaan.


Baru-baru ini saya bekerja pada sistem yang perlu mengurai lalat XML, secara dinamis. File yang lebih besar akan membutuhkan lebih banyak waktu. Ini sangat sensitif terhadap kinerja; parse yang terlalu lambat akan menyebabkan UI menjadi benar-benar tidak dapat digunakan.

Hal-hal semacam ini muncul setiap saat.


Jadi .... terkadang Anda menginginkan kode yang mudah dikelola dan mudah ditulis. Terkadang Anda menginginkan kode yang berjalan cepat. Pengorbanan adalah keputusan rekayasa yang perlu Anda buat, pada setiap proyek.

Cheeso
sumber
9
Dalam semua contoh Anda biaya untuk mengoptimalkannya setelah itu tidak jauh lebih tinggi daripada menulis kode cepat dari awal. Jadi, menulis kode lebih lambat lebih lambat pertama dan kemudian mengoptimalkan di mana perlu bekerja dengan baik di semua itu.
CodesInChaos
6
@CodeInChaos: Jawabannya tidak mengklaim sebaliknya. Ini berbicara pada pertanyaan OP, "Mengapa saya harus peduli dengan kinerja mikro dan efisiensi?" Masalah pra-optimasi hanya disimpulkan oleh penjawab lain.
webbiedave
12

Jika Anda memproses gambar besar dan mengulangi setiap piksel, maka penyesuaian kinerja dapat menjadi sangat penting.

Steve Wellens
sumber
2
+1 - juga, keuangan frekuensi tinggi, segala jenis encoder / decoder audio / video, simulasi dan pemodelan (misalnya game), bit seluruh sistem seperti penjadwal CPU dan manajer memori, dll.
Billy ONeal
3
BISA kritis, tapi IS hanya kritis setelah Anda membuktikannya begitu dan Anda telah menjadikannya di tempat yang menurut Anda masalahnya. (Petunjuk: mungkin tidak ada di sana.)
HANYA PENDAPATAN SAYA
2
@ HANYA PENDAPAT SAYA yang benar: sebenarnya, untuk pemrosesan gambar, pemrosesan data biasanya merupakan konsumen dengan waktu terbesar kedua (I / O masih merupakan yang terbesar). Namun, mengoptimalkan I / O membutuhkan banyak desain yang tidak biasa / gila dan penerimaannya oleh sesama programmer, dan kadang-kadang tidak mungkin untuk ditingkatkan. Bagian pemrosesan, bagaimanapun, biasanya dapat diparalelkan secara paralel, oleh karena itu mereka adalah manfaat yang dapat digunakan kembali dengan mudah. (Tweak seseorang mungkin dilihat oleh orang lain sebagai implementasi buku teks lurus ... kecuali Anda mencapai tingkat VirtualDub)
rwong
12

Biarkan saya memberi tahu Anda sedikit tentang mengapa di balik budaya.

Jika Anda lebih dekat ke 40 dari pada 20, dan Anda telah memprogram untuk mencari nafkah selama bertahun-tahun dewasa Anda, maka Anda menjadi dewasa ketika C ++ benar-benar satu-satunya permainan di kota, aplikasi desktop adalah norma, dan perangkat keras masih perangkat lunak yang sangat tertinggal dalam hal kemampuan bandwidth / kinerja.

  • Kami dulu harus melakukan trik pemrograman bodoh untuk dapat membaca file besar (> 2G) ...
  • Kami dulu khawatir tentang ukuran yang dapat dieksekusi ...
  • Kami dulu khawatir tentang berapa banyak memori yang dikonsumsi oleh program kami ...
  • Kami secara teratur membuat keputusan algoritme waktu vs ruang angkasa ...
  • Bahkan di back-end, kami harus menulis program CGI di C atau C ++ untuk apa pun untuk menangani no yang layak. dari RPS ... Itu beberapa kali lipat lebih cepat.
  • Kami biasa menjalankan tes berdasarkan kemampuan kinerja antara delphi / c ++ / vb!

Sangat sedikit orang yang khawatir tentang hal-hal ini hari ini.

Namun, 10 tahun yang lalu Anda masih harus khawatir tentang perangkat lunak Anda yang diunduh melalui modem 56kb, dan dijalankan pada PC berusia 5 tahun ... Apakah Anda ingat betapa buruknya PC pada tahun 1996? Pikirkan dalam hal 4GB hard drive, prosesor 200Mhz, dan 128Mb RAM ...

Dan server 10 tahun yang lalu? Server "generasi berikutnya" Dell berharga $ 2000, dan datang dengan 2 (!) Prosesor pentium 1Ghz, 2Gb atau Ram, dan hard drive 20Gb.

Itu hanya ballgame yang berbeda , dan semua insinyur "senior" yang memiliki 10 tahun pengalaman (orang-orang cenderung menjawab pertanyaan Anda), memotong gigi mereka di lingkungan itu.

kotoran merah
sumber
1
Tambahan 20 tahun pengalaman juga berarti kami telah mendapatkan tanda terbakar karena telah melalui proses pengoptimalan berkali-kali dan menghindari melakukan hal-hal yang mungkin memerlukannya nanti. Alasan yang sama saya tidak memukul ibu jari saya (banyak) saat menggunakan palu.
Blrfl
1
lingkaran unwinding <bergidik>
merah-kotoran
5
dan hari ini semua anak-anak yang berpikir bandwidth, CPU dan memori tidak terbatas menemukan aplikasi mobile mereka tidak berfungsi dengan baik.
gbjbaanb
9

sudah ada 10 jawaban di sini dan ada yang benar-benar bagus, tetapi karena ini adalah kesayangan pribadi saya ...

pengoptimalan prematur yang a) membutuhkan lebih banyak waktu untuk dilakukan daripada solusi sederhana b) memperkenalkan lebih banyak kode di mana solusi sederhana akan menjadi setengah dari ukuran dan setengah dari kompleksitas dan c) membuat hal-hal yang kurang dapat dibaca adalah BENAR-BENAR harus dihindari. Namun, jika pengembang memiliki pilihan antara menggunakan std :: map atau std :: vector dan ia memilih koleksi yang salah dari ketidaktahuan murni untuk kinerja yang sama buruknya jika tidak lebih buruk dari optimasi prematur. Bagaimana jika Anda dapat sedikit mengubah kode Anda hari ini, mempertahankan keterbacaan, menjaga kompleksitas yang sama, tetapi membuatnya lebih efisien, apakah Anda akan melakukannya? Atau Anda akan menyebutnya "optimasi prematur"? Saya menemukan bahwa banyak orang bahkan tidak akan memikirkannya dengan cara apa pun.

Suatu ketika saya adalah orang yang menyarankan "optimasi mikro" yang membutuhkan sedikit perubahan dan saya diberi respons yang sama seperti yang Anda katakan, "Anda tidak boleh mengoptimalkan terlalu dini. Mari kita mulai bekerja dan kita akan mengubahnya nanti jika ada masalah kinerja ". Butuh beberapa rilis sebelum kami memperbaikinya. Dan ya itu masalah kinerja.

Walaupun optimasi awal mungkin tidak baik, saya pikir itu sangat bermanfaat jika orang menulis kode dengan memahami apa yang akan dilakukan kode itu dan tidak mengabaikan pertanyaan yang menghasilkan notasi O (x) sebagai "optimasi". Ada banyak kode yang dapat Anda tulis sekarang dan dengan sedikit pemikiran tentang kinerja hindari 80% masalah di ujung jalan.

Juga pertimbangkan bahwa banyak masalah kinerja tidak akan terjadi di lingkungan Anda dan tidak segera. Beberapa kali Anda akan memiliki pelanggan yang mendorong batas atau pengembang lain memutuskan untuk membangun di atas kerangka kerja Anda dan menambah jumlah objek 10 kali lipat. Dengan beberapa tentang kinerja sekarang, Anda dapat menghindari mendesain ulang yang sangat mahal nanti. Dan jika masalah ditemukan setelah perangkat lunak dirilis secara resmi, bahkan perbaikan sederhana menjadi 20 kali lebih mahal untuk diterapkan.

Jadi sebagai kesimpulan, menjaga kinerja dalam pikiran setiap saat membantu mengembangkan kebiasaan baik. Yang sama pentingnya dengan memiliki tulisan bersih, sesederhana mungkin dan kode terorganisir.

DXM
sumber
+1: Ini adalah salah satu faktor kemampuan kerja bagi mereka yang disewa untuk mengembangkan perangkat lunak Shrinkwrap dan situs web Komersial . Pencegahan lebih murah daripada kutukan pelanggan.
rwong
6

Saya menduga bahwa banyak yang Anda lihat adalah kesalahan pengambilan sampel sederhana. Ketika orang berhadapan dengan situasi langsung, mereka menulis kode dan itulah akhirnya. Mereka mengajukan pertanyaan ketika mereka berhadapan dengan sesuatu yang relatif rumit, seperti perlu mengoptimalkan, terutama dalam situasi di mana belum tentu bahwa optimasi akan diperlukan.

Yang mengatakan, pasti ada beberapa optimasi prematur yang terlibat juga. Benar atau tidak, C dan C ++ memiliki reputasi untuk kinerja, yang cenderung menarik orang-orang yang peduli tentang kinerja - termasuk mereka yang dapat melakukan optimasi sebanyak untuk kesenangan seperti karena itu benar-benar diperlukan.

Jerry Coffin
sumber
1
+1 - Catatan: Sebagian besar pertanyaan SO dengan tag "kinerja" mungkin merupakan bagian dari kesalahan pengambilan sampel: P
Billy ONeal
3
Saya yakin melihat banyak pertanyaan pengoptimalan prematur di sini ... Saya pikir itu berasal dari kenyataan bahwa banyak programmer hobi memulai dengan ide untuk menulis game, dan ada kumpulan besar buku "optimasi" omong kosong dan situs web yang terkait dengan pengembangan game yang menempatkan ide-ide buruk di kepala para pemula. :-)
R ..
4
Ketika Anda berurusan dengan sesuatu yang rumit, sering kali tampaknya lebih mudah untuk beristirahat dari masalah yang rumit dan membuang waktu Anda untuk mengkhawatirkan apakah Anda harus menggunakan i++atau++i
Carson63000
@ Carson63000: ya itu benar-benar dapat memiringkan sampel. Atau mereka menghabiskan waktu menjawab pertanyaan tentang mengapa saya operator ++tidak mengkompilasi.
rwong
4

Beberapa jawaban lain menyebutkan embedded system , dan saya ingin memperluas ini.

Ada banyak perangkat yang mengandung prosesor low-end, misalnya: pengontrol ketel di rumah Anda, atau kalkulator saku sederhana, atau lusinan keripik di dalam mobil modern.

Untuk menghemat uang, ini mungkin memiliki jumlah flash (untuk menyimpan kode) dan RAM yang tampak kecil bagi mereka yang hanya memiliki kode tertulis untuk PC atau smartphone. Untuk menghemat daya, mereka dapat berjalan pada kecepatan clock yang relatif rendah.

Sebagai contoh, keluarga mikrokontroler STM32 bergerak dari 24 MHz, 16 KB flash dan 4 KB RAM , hingga 120 MHz, 1 MB flash dan 128 KB RAM .

Saat menulis kode untuk chip seperti ini, akan menghemat banyak waktu jika Anda ingin membuat kode Anda seefisien mungkin. Jelas, optimasi prematur tetap merupakan ide yang buruk; tetapi dengan latihan, Anda belajar bagaimana masalah umum dapat diselesaikan dengan cepat dan / atau dengan sumber daya minimal, dan kode sesuai.

Steve Melnikoff
sumber
1
poin bagus untuk dipertimbangkan untuk embedded system, bidang yang saya kerjakan sendiri. Bahkan dengan itu dalam pikiran pengalaman saya selama bertahun-tahun adalah bahwa optimasi salah arah selalu membuang-buang waktu. Tanpa alat untuk membimbing kita, kita jarang menemukan area masalah
Jeff
2

Ini menjadi dasarnya bahasa tingkat rendah, ketika salah satu berjalan ke kasus kinerja patologis di mana salah satu detail yang tidak akan peduli 99% dari waktu yang menyebabkan para bottleneck, yang benar-benar memiliki kesempatan untuk langsung bekerja di sekitar masalah (tidak seperti kebanyakan lainnya bahasa); tetapi tentu saja, sering kali, cara melakukannya secara paling efektif tidak segera terlihat. Karenanya setengah dari pertanyaan optimasi mikro yang aneh / menarik ditanyakan di sini.

Setengah lainnya hanya berasal dari mereka yang penasaran tentang seberapa dekat mereka dengan logam. Ini menjadi bahasa tingkat rendah pada dasarnya, setelah semua ...

ildjarn
sumber
+1: layak menunjukkan bahwa "kinerja patologis" dapat terjadi pada siapa pun di dunia, terlepas dari bahasa atau platform. Kemampuan untuk menerapkan kembali dalam bahasa tingkat rendah untuk menguji dan membaca pembongkaran dapat memberikan lebih banyak wawasan , tetapi tidak selalu memberikan solusi yang bisa diterapkan. Contoh: "Saya tahu saya bisa melakukannya dalam perakitan - tetapi harus dijalankan di lingkungan kepercayaan parsial!"
rwong
2

Kinerja selalu menjadi topik hangat saat Anda berurusan dengan C dan C ++. Mengenai seberapa jauh seseorang harus melangkah, Anda selalu bisa menjadi gila sampai-sampai ASM sebaris, atau menggunakan aritmatika pointer untuk iterasi yang lebih cepat. Namun, ada titik di mana seseorang menghabiskan begitu banyak waktu untuk mengoptimalkan sehingga bekerja untuk mengembangkan program secara keseluruhan terhenti.

Saat menangani masalah ini, ada kinerja programmer dan kinerja kode. Yang mana dari ini untuk fokus akan selalu memunculkan pertanyaan menarik. Pada akhirnya pertanyaan yang paling penting adalah seberapa nyata hal itu bagi pengguna. Apakah pengguna akan bekerja dengan data yang menciptakan array dengan ratusan atau ribuan elemen? Dalam hal ini, pengkodean untuk menyelesaikan sesuatu dengan cepat mungkin membuat pengguna Anda mengeluh bahwa operasi standar program lambat.

Lalu ada pengguna yang akan bekerja dengan sejumlah kecil data. Beberapa file di sana-sini, tempat melakukan hal-hal seperti penyortiran dan operasi file tidak akan terlihat bagi pengguna jika Anda menggunakan fungsi tingkat yang lebih tinggi yang membuat Anda lebih mudah untuk mempertahankannya dengan mengorbankan beberapa kinerja.

Ini hanyalah contoh kecil dari masalah yang akan Anda hadapi. Hal-hal lain termasuk perangkat keras pengguna target. Anda harus lebih khawatir tentang kinerja lebih banyak jika Anda berurusan dengan sistem tertanam, maka jika pengguna Anda memiliki, katakanlah, mesin dual core dengan gigs of ram.

onteria_
sumber
Hmm .. Saya tidak menggunakan pointer aritmatika untuk iterasi yang lebih cepat - ini adalah perkalian dan tambahkan instruksi per loop apakah Anda menggunakan pengindeksan berbasis indeks atau berbasis pointer. Saya memang menggunakannya, karena biasanya lebih jelas daripada iterasi berbasis indeks.
Billy ONeal
aritmatika pointer tidak lebih cepat dari w / e.
2

Mengapa programmer sangat peduli? Ada ide-ide konyol mengisi kepala mereka, seperti menyelesaikan masalah kinerja sebelum mereka tahu mereka memilikinya, dan tidak memahami ketika mereka menebak .

Ini sulit karena, dalam pengalaman saya, ada beberapa masalah kinerja yang harus dipikirkan sebelumnya. Butuh pengalaman untuk mengetahui siapa mereka.

Yang mengatakan, metode yang saya gunakan mirip dengan Anda, tetapi tidak sama:

  1. Mulailah dengan desain sesederhana mungkin. Secara khusus, struktur data harus dinormalisasi dan seminimal mungkin. Sejauh ia memiliki redundansi yang tak terhindarkan, orang harus menghindari pemberitahuan sebagai cara untuk membuatnya konsisten. Lebih baik mentolerir ketidakkonsistenan sementara, dan memperbaikinya dengan proses berkala.

  2. Ketika program sedang dalam pengembangan, lakukan penyetelan kinerja secara berkala, karena masalah kinerja memiliki cara yang diam-diam merayap masuk. Metode yang saya gunakan adalah jeda acak , karena saya pikir itu yang terbaik.

Inilah contoh pukulan demi pukulan tentang apa yang saya maksud.

Mike Dunlavey
sumber
1

Sejujurnya, itu tergantung pada apa tujuan Anda dan apakah Anda pemrograman secara profesional atau sebagai hobi.

Saat ini, komputer modern adalah mesin yang sangat kuat. Terlepas dari operasi dasar apa yang Anda putuskan untuk dilakukan, apakah Anda mencoba untuk mengoptimalkan mikro atau tidak, mereka dapat membuat pekerjaan mereka sangat cepat. Tetapi tentu saja, jika Anda melakukan sesuatu yang lain (misalnya, superkomputasi untuk bidang-bidang seperti fisika atau kimia), Anda mungkin ingin mengoptimalkan sebanyak yang Anda inginkan.

Para programmer MIT awal tidak dilahirkan untuk membuat hal-hal yang luar biasa; Mereka mulai menyederhanakan dan memberi daya pada algoritma yang ada. Kebanggaan mereka adalah membuat 2 + 2 memberi empat dalam dua detik kurang dari algoritma yang ada (itu hanya contoh, Anda mendapatkan ide). Mereka terus-menerus mencoba menggunakan lebih sedikit kartu punch di mesin TI-83 mereka untuk kinerja.

Juga, jika Anda memprogram untuk sistem embedded, maka Anda tentu harus mengawasi kinerja mikro. Anda tidak ingin memiliki jam digital lambat yang berdetik 5 milidetik detik lebih awal dari jam digital lainnya.

Akhirnya, jika Anda seorang programmer hobi maka tentu tidak ada salahnya mengoptimalkan detail terkecil meskipun program Anda cepat itu. Ini tidak diperlukan, tetapi tentu saja sesuatu yang dapat Anda kerjakan dan ambil kesempatan untuk mempelajari lebih lanjut. Jika Anda bekerja secara profesional dalam sebuah perangkat lunak, Anda tidak dapat mengambil kemewahan itu kecuali sangat diperlukan.

Andy Ibanez
sumber
1
Saya tidak berpikir menjadi programmer hobi ada hubungannya dengan ini. Hanya karena Anda tidak melakukan sesuatu secara profesional tidak berarti Anda memiliki seluruh waktu di dunia untuk dihabiskan untuk itu. Selain itu, sebagian besar penggemar akan membuat kesalahan yang lebih besar, seperti memilih algoritma yang salah, daripada kebanyakan profesional sejati akan membuat. Selain itu, profesional mungkin sedang mengerjakan produk yang memproses lebih banyak data secara signifikan daripada penghobi (yang karenanya harus lebih cepat), dan harus membuat pelanggan senang dengan kinerja aplikasi. Hobi tidak memiliki kendala seperti itu.
Billy ONeal
Mereka tidak, tetapi mereka tentu memiliki lebih banyak waktu untuk mengerjakannya hanya jika mereka mau.
3
Saya berpendapat sebaliknya. Saya punya 8 jam atau lebih sehari untuk mengerjakan sesuatu sebagai seorang profesional. Saya mendapat 1, mungkin 2 jam per hari untuk proyek hobi saya.
Billy ONeal
1

menggunakan algoritma O (N2) vs O (NlogN) pada daftar 100 item.

Saya berada dalam situasi yang sama baru-baru ini. Saya memiliki berbagai item. Dalam kasus yang diharapkan, ada dua item (!) Dalam daftar, dan bahkan dalam kasus terburuk saya tidak mengharapkan lebih dari empat atau mungkin delapan.

Saya perlu mengurutkan daftar itu. Ternyata, mengganti std::sortdengan jaringan penyortiran (pada dasarnya banyak bersarang if) memangkas sebagian besar waktu berjalan (saya tidak ingat nomornya tapi itu kira-kira 10-20%). Ini adalah manfaat besar dari optimasi mikro, dan kode ini benar-benar kritis terhadap kinerja.

Tentu saja, saya hanya melakukan ini setelah membuat profil. Tetapi intinya adalah, jika saya menggunakan bahasa yang tidak nyaman dan berbelit-belit seperti C ++ (belum lagi aturannya yang rumit dan rumit untuk resolusi kelebihan beban), maka saya ingin menuai manfaat penuh.

Konrad Rudolph
sumber
1

Penggunaan energi kumulatif

Ada satu jawaban yang menurut saya selalu hilang dari diskusi ini dan yang sedikit mengganggu saya - penggunaan energi kumulatif .

Tentu, mungkin tidak masalah jika Anda menulis program Anda dalam bahasa tingkat tinggi yang ditafsirkan, dan membiarkannya berjalan di browser dengan beberapa lapisan tipuan, atau jika loop Anda membutuhkan 0,01 detik, bukan 0,001 detik. Tidak ada yang akan melihat, yaitu, tidak ada pengguna individu akan melihat.

Tetapi ketika puluhan ribu, atau bahkan jutaan pengguna dalam beberapa kasus menggunakan kode Anda, semua itu menambah inefisiensi tambahan. Jika alat Anda mencegah CPU memasuki kondisi tidur hanya sepuluh detik per hari, dan sejuta pengguna menggunakannya, algoritma Anda yang tidak efisien hanya menghabiskan 140 kWh [1] per hari.

Saya jarang melihat ini dibahas, dan saya pikir itu menyedihkan. Saya sangat curiga bahwa angka-angka itu jauh lebih buruk untuk kerangka kerja populer, seperti Firefox, dan aplikasi web interaktif yang bagus, dan itu akan menarik untuk diteliti.


[1] Saya baru mengarangnya, 10 juta detik kali 50 Watt. Angka pastinya tergantung pada banyak hal.

pipa
sumber
1
Anda harus memulai dengan menyebutkan kata ajaib "ponsel". Saat berjalan pada platform desktop, aplikasi yang membutuhkan waktu CPU 1/100 detik untuk menggambar bingkai 60 kali per detik akan "cukup cepat"; meningkatkan kinerja sepuluh kali lipat akan membuat perbedaan nol bagi pengguna. Pada platform seluler, aplikasi yang berjalan pada utilisasi CPU 90% dapat mengurangi baterai lebih cepat dari pada berlari 10%.
supercat
1

Kadang-kadang Anda hanya memiliki algoritma yang tidak bisa lebih baik daripada waktu linear yang masih memiliki permintaan kinerja yang kuat.

Contohnya adalah pemrosesan video di mana Anda tidak dapat membuat gambar / bingkai lebih terang sebagai contoh dasar tanpa mengulangi setiap piksel (well, saya kira Anda bisa dengan semacam struktur hierarki yang menunjukkan properti yang diwarisi oleh anak-anak yang akhirnya turun ke ubin gambar untuk simpul daun, tetapi kemudian Anda akan menunda biaya perulangan yang lebih tinggi melalui setiap piksel ke penyaji dan kode mungkin akan lebih sulit dipertahankan daripada filter gambar yang paling dioptimalkan secara mikro).

Ada banyak kasus seperti itu di bidang saya. Saya cenderung melakukan loop kompleksitas-linear yang harus menyentuh segala sesuatu atau membaca semuanya daripada yang mendapat manfaat dari segala jenis struktur data atau algoritma yang canggih. Tidak ada pekerjaan yang dapat dilewati ketika semuanya harus disentuh. Jadi pada saat itu jika Anda berurusan dengan kompleksitas linear, Anda harus membuat pekerjaan yang dilakukan lebih murah dan lebih murah.

Jadi dalam kasus saya optimisasi yang paling penting dan umum sering representasi data dan tata letak memori, multithreading, dan SIMD (biasanya dalam urutan ini dengan representasi data menjadi yang paling penting, karena memengaruhi kemampuan untuk melakukan dua yang terakhir). Saya tidak mengalami begitu banyak masalah yang bisa diselesaikan oleh pohon, tabel hash, algoritma pengurutan, dan hal-hal semacam itu. Kode harian saya lebih sesuai, "untuk setiap hal, lakukan sesuatu."

Tentu saja itu adalah kasus lain untuk dibicarakan ketika optimasi diperlukan (dan yang lebih penting, ketika tidak), mikro atau algoritmik. Tetapi dalam kasus khusus saya, jika jalur eksekusi yang kritis memerlukan optimasi, peningkatan kecepatan 10x + sering dicapai oleh optimasi tingkat mikro seperti multithreading, SIMD, dan menata ulang susunan memori dan pola akses untuk meningkatkan lokalitas referensi. Tidak sering saya dapat, misalnya, mengganti semacam gelembung dengan introsort atau semacam radix atau deteksi tabrakan kompleksitas kuadratik dengan BVH sehingga banyak menemukan hotspot yang, katakanlah, manfaat dari pemisahan bidang panas / dingin.

Sekarang dalam kasus saya, bidang saya sangat kritis terhadap kinerja (raytracing, mesin fisika, dll) sehingga raytracer yang lambat namun benar-benar sempurna yang membutuhkan 10 jam untuk membuat gambar sering dianggap tidak berguna atau lebih cepat daripada yang cepat yang sepenuhnya interaktif tetapi menampilkan gambar yang paling jelek dengan sinar yang bocor di mana-mana karena kurangnya sinar kedap air / persimpangan tri. Kecepatan bisa dibilang metrik kualitas utama dari perangkat lunak tersebut, bahkan bisa dibilang lebih dari benar sampai titik tertentu (karena "kebenaran" adalah ide kabur dengan raytracing karena semuanya mendekati, asalkan tidak menabrak atau semacamnya). Dan ketika itu masalahnya, jika saya tidak memikirkan efisiensi di muka, saya merasa saya harus benar-benar mengubah kode pada level desain paling mahal untuk menangani desain yang lebih efisien. Jadi jika saya tidak

Game adalah bidang lain yang mirip dengan milikku. Tidak masalah seberapa benar logika gim Anda atau seberapa basis kode Anda yang dapat dipertahankan dan direkayasa dengan cemerlang jika gim Anda berjalan dengan kecepatan 1 frame per detik seperti tampilan slide. Di bidang-bidang tertentu kurangnya kecepatan sebenarnya bisa membuat aplikasi tidak berguna bagi penggunanya. Tidak seperti game, tidak ada metrik "cukup baik" di area seperti raytracing. Para pengguna selalu menginginkan lebih banyak kecepatan, dan persaingan industri terutama dalam mencari solusi yang lebih cepat. Ini tidak akan pernah cukup baik sampai saat itu juga, di mana game akan menggunakan pelacak jalur. Dan mungkin itu masih belum cukup baik untuk VFX, karena para seniman mungkin ingin memuat miliaran poligon dan melakukan simulasi partikel dengan tabrakan sendiri di antara miliaran partikel pada 30+ FPS.

Sekarang jika itu kenyamanan, meskipun begitu saya masih menulis sekitar 90% dari kode dalam bahasa scripting (Lua) tanpa khawatir tentang kinerja apa pun. Tetapi saya memiliki jumlah kode yang luar biasa besar yang sebenarnya perlu di-loop melalui jutaan hingga milyaran hal, dan ketika Anda mengulang-ulang jutaan hingga milyaran, Anda mulai melihat perbedaan epik antara kode single-threaded yang naif yang mengaktifkan cache miss dengan setiap iterasi vs. katakanlah, kode vektor berjalan di paralel mengakses blok yang berdekatan di mana tidak ada data yang tidak relevan dimuat ke dalam garis cache.

user204677
sumber
0

Seperti yang Anda sebutkan, kepedulian tentang masalah kinerja mikro tidak ada artinya sebelum Anda memperhitungkan beberapa masalah yang sebenarnya disebabkan oleh masalah ini

huubby
sumber
0

Sangat tidak mungkin untuk menjawab pertanyaan ini secara umum. Sebagian besar perangkat lunak yang sedang dibangun saat ini adalah situs web internal dan aplikasi LOB, dan untuk pemrograman semacam itu alasan Anda cukup tepat. Di sisi lain, jika Anda menulis sesuatu seperti driver perangkat atau mesin gim, tidak ada optimasi yang "prematur"; kemungkinan perangkat lunak Anda akan berjalan pada sistem yang sangat berbeda dengan batasan perangkat keras yang berbeda. Dalam hal ini Anda harus merancang untuk kinerja dan pastikan Anda tidak memilih algoritma yang kurang optimal.

Nemanja Trifunovic
sumber
Persis apa yang ingin saya katakan. Setiap perangkat lunak memiliki domain aplikasinya dan tidak diharapkan berperilaku optimal di luarnya. Dalam hal ini, optimasi prematur adalah contoh perfeksionisme yang salah arah.
K.Steff
0

Saya pikir masalah programmer, yang sangat peduli dengan kinerja adalah, bahwa kadang-kadang dalam hidupnya, dia perlu menulis kode mikro-kinerja, mungkin sangat mendesak, dan dia belajar, belajar, belajar, dan pada akhirnya dia tahu banyak hal dan trik.

Dan sekarang sulit untuk dilupakan, dan tanpa pengukuran sebelumnya, yang menunjukkan, bahwa dia tidak perlu khawatir, dia berada di sisi yang aman, menggunakan kode cepat.

Selalu menyenangkan untuk menunjukkan pengetahuan mendalam Anda, keterampilan Anda dan beberapa trik, dan menggunakan kembali sesuatu yang telah Anda pelajari. Itu membuat Anda merasa berharga, dan waktu, dihabiskan untuk belajar, menjadi layak.

Kadang-kadang dalam hidup saya, saya belajar peningkatan awalan lebih cepat ...

for (int i = 0; i < MAX; ++i)

... dari penambahan postfix:

for (int i = 0; i < MAX; i++)

Sekarang jika MAX rendah, itu tidak masalah, dan jika ada pekerjaan nyata dalam loop, itu tidak masalah juga. Tetapi tidak ada alasan untuk menggunakan versi postfix, bahkan jika kompilator hari ini mengoptimalkan kode mereka sendiri.

Mungkin para pencari kinerja memerlukan tujuan tambahan, selain menulis 'kode kerja', seperti 'kode kerja dan mudah dibaca' untuk memiliki pedoman dalam banyak pilihan.

Pengguna tidak diketahui
sumber
0

Apakah saya hanya cukup beruntung untuk tidak perlu terlalu khawatir tentang hal itu, atau apakah saya seorang programmer yang buruk?

Apakah Anda peduli dengan kebutuhan Anda? Jika kinerja bukan keharusan maka jangan khawatir. Menghabiskan waktu yang signifikan untuknya adalah merugikan majikan Anda.

Sampai taraf kinerja selalu merupakan persyaratan. Jika Anda dapat memukulnya tanpa memikirkannya, Anda dibenarkan karena tidak memikirkannya.

Secara pribadi, saya paling sering didorong oleh kinerja ketika tes saya butuh waktu lama untuk lulus. Saya terlalu tidak sabar untuk menunggu 5 menit sementara serangkaian tes berlalu. Tapi itu biasanya diselesaikan dengan mengutak-atik tes.

Pertanyaan saya adalah mengapa sejumlah besar programmer begitu peduli? Apakah ini benar-benar masalah bagi sebagian besar pengembang,

Ada sejumlah besar programmer yang dibenarkan dalam hal seberapa peduli mereka. Ada sejumlah besar yang tidak. Mari kita bicara tentang mereka yang tidak.

Salah satu hal pertama yang dipelajari programmer di sekolah, setelah bagaimana membuat hal-hal benar-benar berfungsi, adalah notasi O besar. Banyak dari mereka mempelajari pelajaran dengan benar dan dengan demikian berfokus pada hal-hal yang secara dramatis dipengaruhi oleh n. Yang lain tidak mendapatkan matematika dan hanya mengambil pelajaran bahwa begitu berhasil perlu cepat. Lebih buruk lagi, beberapa siswa ini tidak pernah belajar hal lain tentang apa yang penting dilakukan dengan kode Anda selain membuatnya bekerja dan membuatnya bekerja cepat. Pelajaran yang terlewatkan: membuatnya dapat dibaca, rancang dengan baik, jangan bermain-main di dalamnya tanpa alasan.

Knuth benar: optimasi prematur adalah akar dari semua kejahatan. Tapi begitu berhasil apa langkah selanjutnya? Cepat kan? TIDAK! Langkah selanjutnya bisa dibaca. Dapat dibaca adalah langkah pertama, berikutnya, tengah, dan terakhir. Banyak orang yang saya temukan melakukan optimasi kinerja yang tidak dibutuhkan sedang melempar keterbacaan di bawah bus.

Beberapa bahkan mendapatkan sensasi sesat dari betapa tidak terbacanya kode mereka. Mereka harus menderita melihat sulit untuk memahami kode yang dibuat oleh orang lain jadi sekarang giliran mereka di payback.

Saya tahu ini karena saya biasa melakukan ini. Saya pernah refactored 5 baris yang dapat dibaca dengan sempurna jika struktur turun ke ekspresi boolean satu baris yang tidak dapat dipahami dan dengan bangga mengirimkannya kepada profesor saya berharap untuk mengesankan karena saya bisa membuat sesuatu yang begitu kompak dan mengintimidasi. Saya tidak mendapatkan pujian yang saya harapkan.

Jika kode tetap dapat dibaca membuatnya cepat nanti mudah. Itu sebabnya Knuth menekankan "prematur" bukan "tidak dibutuhkan". Karena yakin, lebih cepat lebih baik. Tetapi lebih baik hanya lebih baik tergantung pada apa yang Anda korbankan untuk itu. Jadi tunggu sampai Anda tahu kinerja apa yang benar-benar Anda butuhkan sebelum Anda berkorban untuk itu. Keterbacaan pengorbanan enggan karena setelah hilang, sulit untuk kembali.

Di luar keterbacaan adalah seluruh dunia desain perangkat lunak. Tentang apa situs ini. Beberapa tidak memiliki petunjuk apa yang harus dilakukan sejauh desain. Jadi karena mereka tidak dapat mengesankan dengan desain, mereka membuat kekacauan yang tidak dapat dipahami sehingga orang tidak tahu bahwa mereka tidak tahu. Karena tidak ada yang pernah memperbaiki kode mereka, itu pasti kode yang bagus, kan?

Bagi sebagian orang, kinerja adalah alasan utama untuk melakukan apa pun yang mereka inginkan. Programmer memiliki banyak kekuatan dan otonomi. Kepercayaan telah diberikan pada mereka. Jangan menyalahgunakan kepercayaan.

CandiedOrange
sumber