Belajar untuk mengoptimalkan dengan Majelis [ditutup]

21

Saya seorang siswa tahun kedua Teknologi Game Komputer. Saya baru saja menyelesaikan prototipe pertama dari "jenis" pathfinder saya sendiri (yang tidak menggunakan A * alih-alih pendekatan geometris / pengenalan pola, pathfinder hanya perlu pengetahuan tentang medan yang menurut pandangannya untuk membuat keputusan, karena saya ingin AI yang benar-benar bisa menjelajah, jika medannya sudah diketahui, maka ia akan berjalan dengan cara terpendek dengan mudah, karena pathfinder memiliki memori node).

Pokoknya pertanyaan saya lebih umum: Bagaimana cara saya mulai mengoptimalkan algoritma / loop / for_each / etc. menggunakan Majelis, meskipun kiat umum dipersilakan. Saya secara khusus mencari buku yang bagus, karena sangat sulit untuk menemukan buku yang bagus tentang topik ini. Ada beberapa artikel kecil di luar sana seperti ini , tetapi masih belum cukup pengetahuan untuk mengoptimalkan algoritma / permainan ...

Saya harap ada buku bagus dan modern di luar sana, yang tidak dapat saya temukan ...

niktehpui
sumber
1
Ini tidak menjawab pertanyaan Anda secara langsung, tetapi eksploratif (disebut adaptif) A * telah diselidiki dan memiliki kinerja yang sangat baik (artinya Anda tidak perlu mengoptimalkannya menggunakan ASM). Lihatlah D * Lite .
Jonathan Dickinson

Jawaban:

21

Saya akan menjadi orang yang menentang butir-butir di sini dan mengatakan, tidak pernah terlalu dini untuk belajar tentang optimasi, terutama optimasi perakitan dan yang lebih penting, debugging dalam perakitan. Saya percaya bahwa Anda akan mendapatkan manfaat maksimal dari itu jika Anda seorang siswa (karena Anda memiliki sedikit kehilangan (yaitu waktu / uang bijaksana)) dan segalanya untuk mendapatkan.

Jika Anda berada di industri dan tidak ditugaskan untuk bermain-main dalam perakitan, maka jangan. Kalau tidak, jika Anda seorang siswa atau memiliki waktu secara umum, saya akan menemukan waktu untuk belajar membongkar program dan melihat apakah saya dapat menemukan solusi yang lebih baik daripada kompiler. Jika saya tidak bisa, siapa yang peduli! Saya baru belajar cara menulis dan juga kompiler dan itu adalah plus BESAR ketika Anda dihadapkan dengan bug dalam kode rilis (tanpa simbol debug) dan menatap pembongkaran karena itulah satu-satunya hal yang dapat Anda lihat.

Jawabannya

Ini adalah salah satu sumber daya terbaik yang saya temukan untuk belajar tentang optimasi.

http://www.agner.org/optimize/

Kata-kata kasar

Jika Anda membaca beberapa artikel oleh pengembang besar (misalnya, alasan di balik pembuatan EASTL dan pemeriksaan kode yang lebih dekat akan mengarahkan Anda ke komentar seperti melakukan ini karena GCC sangat buruk dalam menguraikan pernyataan if ini yang akan memberi tahu Anda, apa mayoritas orang-orang mengatakan Anda percaya kompiler tidak selalu benar, TERUTAMA dalam pengembangan game) dan kemudian menginjakkan kaki di industri Anda akan menemukan bahwa optimasi adalah hal sehari-hari dan mengetahui apa artinya output perakitan adalah nilai tambah yang besar. Selain itu, orang-orang tampaknya tidak menyadari (terutama pada stackoverflow) bahwa permainan profil sangat sulit dan tidak selalu akurat.

Namun ada peringatan. Anda dapat menghabiskan waktu untuk mengoptimalkan sesuatu dan kemudian menyadari bahwa itu adalah waktu yang terbuang. Tapi apa yang kamu pelajari? Anda belajar untuk tidak mengulangi kesalahan yang sama dalam keadaan yang sama.

Apa yang sekarang diambil oleh SO menurut pendapat saya adalah sikap religius terhadap pernyataan itu tidak mengoptimalkan sampai Anda profil dan jangan khawatir, kompiler tahu lebih baik daripada Anda . Ini menghambat pembelajaran. Saya tahu para ahli di industri yang dibayar dengan uang yang sangat baik (dan maksud saya uang yang SANGAT bagus) untuk bermain-main dalam perakitan untuk mengoptimalkan permainan dan men-debug itu karena kompiler buruk dalam hal itu atau tidak bisa membantu Anda, karena, yah, itu tidak bisa (crash terkait GPU, crash ketika data yang terlibat tidak mungkin untuk dibaca dalam debugger dll.)!

Bagaimana jika seseorang yang suka melakukan itu, belum sepenuhnya menyadarinya, mengajukan pertanyaan di sini dan ditolak / dimatikan oleh banyak jawaban yang diketahui kompiler lebih baik daripada Anda! dan tidak pernah menjadi salah satu programmer yang dibayar tinggi?

Satu pemikiran terakhir. Jika Anda mulai melakukan ini lebih awal, Anda akan menemukan bahwa segera Anda akan mulai menulis kode yang paling buruk, tidak memiliki peningkatan kinerja apa pun karena kompiler mengoptimalkannya dengan cara yang sama atau paling baik, memiliki beberapa peningkatan kinerja karena sekarang kompiler dapat mengoptimalkannya . Dalam kedua kasus itu, sudah menjadi kebiasaan, dan Anda tidak lebih lambat dalam menulis kode dengan cara ini daripada apa yang Anda lakukan sebelumnya. Beberapa contoh adalah (ada banyak lagi):

  1. Pra-kenaikan kecuali jika Anda benar-benar ingin pasca-kenaikan
  2. Menulis loop untuk wadah menggunakan variabel ukuran lokal konstan daripada memanggil ukuran () pada wadah dalam loop.

EDIT: Pembaruan setelah 8 tahun lagi dalam industri ini. Pelajari perakitan. Pelajari cara kerja pengoptimal dan perakitan yang mereka hasilkan (CompilerExplorer adalah alat yang hebat untuk itu). Saya telah menemukan crash yang tak terhitung jumlahnya di Test builds (build dioptimalkan untuk pengujian internal) di mana Anda tidak dapat mengandalkan debugger bahkan dengan simbol debug. Kompiler telah mengoptimalkan terlalu banyak hal dan perakitan adalah satu-satunya sumber informasi berharga Anda untuk menemukan bug dari crash dump. Setiap build membutuhkan waktu 30-40 menit jika Anda beruntung dan yang pertama dalam antrean build - jadi Anda tidak dapat mengandalkan beberapa teknik tradisional untuk mengisolasi bug. Multiplayer membuat segalanya lebih buruk. Mengetahui perakitan dan cara membaca perakitan yang dioptimalkan hanya akan membuat Anda lebih baik dan pada akhirnya lebih berharga bagi tim.

Samaursa
sumber
1
Poin bagus tentang mengoptimalkan kompiler. Mereka hebat untuk dimiliki, tetapi mereka jauh dari sempurna, dan tidak seperti apa yang diyakini sebagian orang, biasanya tidak sulit untuk menemukan optimasi sederhana yang tidak dilakukan oleh kompiler.
aaaaaaaaaaaa
3
Perlu dicatat bahwa ada perbedaan antara "belajar membaca perakitan" dan "belajar mengoptimalkan dengan perakitan". Keduanya bukan hal yang sama, dan jawaban Anda tidak benar-benar menyentuh menggunakan perakitan untuk menerapkan optimisasi. Membaca rakitan adalah keterampilan yang berguna, karena dapat membantu dalam debugging dan melihat tempat-tempat di mana kompiler tidak melakukan sesuatu dengan benar. Tapi itu sangat berbeda dari benar-benar menggunakan perakitan untuk menulis rutin yang dioptimalkan, yang membutuhkan pengetahuan mendalam tentang penjadwalan instruksi untuk CPU tertentu. Dan itu juga sesuatu yang tidak Anda liput.
Nicol Bolas
1
Juga, "Saya baru belajar cara menulis dan juga kompiler" Tidak, Anda tidak melakukannya. Anda melihat bagaimana satu rutin khusus dikompilasi untuk satu CPU tertentu. Mempelajari bagaimana menerapkan rutin perakitan yang dioptimalkan membutuhkan lebih dari sekadar melihat bagaimana kompiler menyusun satu rutin. Anda harus memahami mengapa kompiler memilih opcode tersebut agar dapat mereproduksi kode C ++ tertentu. Dan itu membutuhkan pengetahuan intim tentang CPU, penjadwalan instruksi, dan sebagainya. Generalisasi ini membutuhkan pengalaman bertahun - tahun ; Anda tidak akan mendapatkannya hanya dengan mendekodekan beberapa rutinitas.
Nicol Bolas
7
Jadi, -1 untuk A: tidak benar-benar menjawab pertanyaan tentang cara menulis rutin yang dioptimalkan perakitan. B: salah mengartikan betapa mudahnya mempelajari cara mengalahkan kompiler saat menulis rutin yang dioptimalkan perakitan. Dan C: mendorong seorang programmer untuk melihat optimasi level perakitan sebelum optimasi level algoritma. Bahkan "para pakar dalam industri" yang dibayar tinggi itu akan memberi tahu Anda bahwa menempatkan kereta di depan kuda.
Nicol Bolas
2
@ Sasama: Tidak ada yang mengatakan bahwa orang tidak boleh "memahami pembongkaran dan bagaimana mengoptimalkan kode." Ini bukan perdebatan agama; ini masalah fakta sederhana. Orang-orang telah menghabiskan waktu berabad-abad untuk mengoptimalkan beberapa rutinitas secara manual hanya untuk mengetahui bahwa itu tidak ada artinya bagi kinerja keseluruhan. Mempelajari cara mengoptimalkan algoritma adalah keahlian yang sangat berharga. Belajar membaca majelis merupakan keterampilan yang sangat berharga. Mempelajari cara menulis rutinitas perakitan adalah keterampilan yang jarang digunakan. Dan hari-hari ini, optimasi terbaik berasal dari pemanfaatan cache yang lebih baik, bukan perakitan tangan.
Nicol Bolas
22

Kiat pertama yang akan Anda dapatkan adalah ini - jangan.

Kompiler modern sebenarnya sangat pandai mengoptimalkan kode, dan akan lebih mungkin melakukan pekerjaan yang lebih baik daripada bahasa rakitan yang Anda tulis sendiri.

Pengecualian akan menjadi kasus khusus di mana Anda telah menentukan dengan pasti bahwa kompiler melakukan pekerjaan yang buruk untuk mengoptimalkan, jadi itulah tip kedua. Tidak ada pedoman umum di sini, Anda perlu mengetahui kode Anda sendiri, tahu apa yang dilakukannya, dapat melompat ke dalam pembongkaran itu, dan dapat menentukan dengan pasti bahwa kompiler melakukan pekerjaan yang buruk.

Bahkan dalam hal ini Anda masih mungkin tidak mau. Anda harus yakin bahwa tidak akan ada overhead pemeliharaan yang sedang berlangsung untuk Anda. Anda mungkin ingin kembali ke kode ini dalam waktu 6 bulan dan memodifikasi bagian dari kode ini, atau Anda mungkin menemukan bug yang sangat halus yang akan lebih sulit untuk diperbaiki dalam versi bahasa assembly. Bahkan jika Anda berpikir Anda telah menyelesaikan semua bug, begitu program Anda beralih ke bug publik yang bahkan tidak pernah Anda pikir akan terjadi akan menjadi kenyataan bagi Anda. Itu cukup pembuka mata (dan pengalaman yang merendahkan hati).

Dan bahkan jika Anda senang menerimanya, Anda mungkin masih menemukan bahwa sama sekali tidak ada peningkatan kinerja yang terukur karena hambatan utama Anda mungkin berada di tempat yang sama sekali berbeda dalam program Anda. Sehingga membawa saya kembali ke nomor 1 lagi. Jangan.

Maximus Minimus
sumber
15

Biasanya, pengoptimalan yang solid tidak tergantung pada penggunaan Assembly, atau melakukan optimasi mikro dengan kode dalam bahasa tingkat yang lebih tinggi. Jika Anda membaca banyak makalah penelitian (seperti yang saya lakukan - atau coba!), Anda akan melihat bahwa seringkali perbaikan yang dilakukan untuk algoritma berada pada tingkat konseptual, "kualitatif" yang lebih luas, daripada pada yang lebih "kuantitatif" tingkat optimasi mikro. Saya akan menekankan bahwa keuntungan urutan-besarnya lebih mungkin ditemukan dengan melihat algoritma dari sudut pandang ini, atau dari membuat vektor / memparalelkan solusi yang ada.

Karena itu, saya baru-baru ini mengalami hal ini , yang mungkin merupakan rute yang baik menuju pembelajaran x86 ASM khusus untuk pengembang game.


TAMBAHAN

Dua sumber dari atas kepala saya:

Selain itu, membaca makalah penelitian adalah cara terbaik untuk mengikuti proses pemikiran orang bijak karena mereka mengoptimalkan algoritma untuk kinerja yang lebih baik. Paling sering, keuntungan dilihat oleh:

  • Mengurangi penggunaan operasi yang paling mahal (div, SQRT, triglom, dan kondisional, terutama);
  • Meningkatkan kinerja cache melalui penggunaan struktur data yang lebih efisien, penyelarasan memori, dan pengurangan persyaratan;
  • Mengurangi kualitas output di area yang dapat diterima untuk meningkatkan kinerja;
  • Vektorisasi (SIMD);
  • Parallelisation (threading, termasuk mengalihkan tugas ke GPU);
  • Dan tentu saja (semakin jarang) perakitan kode tangan. Pertama-tama memeriksa majelis C / C ++ untuk melihat di mana kompiler membuat pilihan yang tidak optimal, tentu saja. Anda akan menemukan ini lebih banyak di koran-koran lama dari tahun 80-an dan 90-an, IME.

Membaca penelitian juga membuat Anda berada di ujung tombak bidang Anda, alih-alih menunggu pengetahuan itu untuk disaring ke dalam industri.

Insinyur
sumber
Anda berbicara tentang pengoptimalan algoritma tetapi Anda tidak memberikan informasi tentangnya, jika kami mengikuti saran Anda dan melihat itu, bisakah Anda memberikan arahan?
Skeith
Bahkan, saya menyebutkannya; Anda perlu mempelajari algoritma, memahami apa yang para ilmuwan komputer lakukan untuk meningkatkan kinerja secara kualitatif. Benamkan diri Anda dalam hal ini, dan seiring waktu, Anda mulai berpikir dengan istilah yang sama. Upaya tambahan di sini menghasilkan banyak waktu, dibandingkan dengan menghabiskan bertahun-tahun (dan saya baru-baru ini melihat ini disebutkan di forum ASM) menguasai seluk beluk (adil) misalnya. arsitektur x86. Berburu permainan besar: belajar untuk mengurangi masalah sampai ke intinya, dan kemudian memutuskan apa yang berlebihan untuk mengoptimalkan. Lihat buku referensi di atas.
Insinyur
@NickWiggill Apa sumber makalah penelitian yang biasa Anda gunakan?
kizzx2
3

Saya pikir mungkin terlalu dini.

Bagaimanapun, penting untuk memahami bahwa kompiler itu sendiri tidak menghasilkan kode yang lebih lambat daripada yang setara dengan perakitan, Anda tidak mendapatkan kinerja apa pun hanya dengan menulis kode perakitan yang sama seperti yang dilakukan oleh kompiler.

Sebagai permulaan, setidaknya berkonsentrasilah pada optimisasi bebas perakitan. Igor Ostrovsky memiliki beberapa artikel bagus yang menunjukkan beberapa dasar-dasarnya: http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/

Perhatikan bahwa salah duga cabang dan kesalahan cache adalah yang harus Anda optimalkan, terutama jika Anda harus membayar dengan melakukan beberapa operasi aritmatika tambahan, biasanya layak untuk menghindari cabang yang tidak dapat diprediksi atau membaca secara acak dari terlalu banyak memori.

Dan tentu saja, yang terpenting, optimalkan algoritma Anda terlebih dahulu. Implementasi lambat dari algoritma cepat hampir selalu akan lebih cepat daripada implementasi cepat dari algoritma lambat.

aaaaaaaaaaaa
sumber
2

Buku ini sangat bagus untuk buku teks. Tetapi tidak secara khusus diarahkan pada optimasi. Bahasa Majelis untuk Prosesor x86, edisi ke-6

Ini lebih tentang mengajarkan dasar-dasar perakitan, menggunakan MASM. Kemudian menjelang akhir buku ini masuk ke bagaimana menggabungkan perakitan dengan c ++ dan mengintegrasikannya ke dalam program yang lebih besar.

Saya meletakkan ini di sini karena masuk akal untuk mempelajari dasar-dasar perakitan sebelum Anda belajar bagaimana mengoptimalkan program dengannya.

Saya suka buku ini karena Irvine mengajari Anda cara menggunakan alat yang diperlukan untuk menulis program masm. Dia secara khusus membahas cara menggunakan IDE (Visual Studio C ++) dan debugger. Setiap bab memiliki beberapa video yang didedikasikan untuk memecahkan masalah. Beberapa informasi ini tersedia secara bebas di situs web yang tercantum.

NadtheVlad
sumber
1
"Masuk akal untuk mempelajari dasar-dasar perakitan sebelum Anda belajar bagaimana mengoptimalkan program dengannya" - saran yang bagus.
Maximus Minimus