Rata-rata, seberapa sering perakitan digunakan dalam kode game modern?
Khususnya pada platform yang sudah memiliki kompiler C ++ yang bagus, seperti x86, PPC, atau ARM - karena saya menganggap game pada sistem embedded menggunakan banyak rakitan.
Rata-rata, seberapa sering perakitan digunakan dalam kode game modern?
Khususnya pada platform yang sudah memiliki kompiler C ++ yang bagus, seperti x86, PPC, atau ARM - karena saya menganggap game pada sistem embedded menggunakan banyak rakitan.
Jawaban:
Jawabannya sedikit tergantung pada apa yang Anda maksud dengan "permainan", dan "digunakan". Saya akan menganggap "digunakan" berarti "ditulis selama proyek permainan tertentu".
Dalam pengalaman dan data anekdotal saya dari orang yang saya ajak bicara:
Pengetahuan tentang bahasa assembly tidak diharapkan untuk bekerja di industri game, tetapi tergantung pada jenis game yang Anda buat, itu mungkin menguntungkan.
Dulu ada argumen bahwa kompiler melakukan pekerjaan yang lebih baik dalam mengoptimalkan kode C daripada manusia dengan perakitan tulisan tangan. Biasanya itu benar, kadang itu salah. Tetapi akhir-akhir ini kombinasi dari kompleksitas CPU yang terus tumbuh dan kebutuhan untuk skala 'keluar' (yaitu untuk memisahkan prosesor) berarti bahwa upaya optimasi biasanya dihabiskan di tempat lain.
Dalam beberapa tahun terakhir, satu-satunya waktu saya melihat perakitan dalam kode permainan adalah __asm int 3
pernyataan untuk memaksa breakpoint, dan satu-satunya penggunaan pribadi saya pada perakitan adalah dalam melihat pembongkaran fungsi untuk mendiagnosis bug kecelakaan yang tidak biasa.
Sebagian besar kode kinerja tinggi dalam game konsol modern ditulis menggunakan semacam jalan tengah antara perakitan dan C ++: kompiler intrinsik . Konstruk ini terlihat dan diurai seperti fungsi C ++, tetapi sebenarnya diterjemahkan ke dalam instruksi mesin tunggal . Jadi, misalnya, saya "menjepit setiap nilai vektor V menjadi> = a dan <= b" fungsi seperti
// for each v.x, ensure v.x >= a.x && v.x <= b.x
inline __m128 ClampSIMD( const __m128 &v, const __m128 & a, const __m128 & b )
{
return _mm_max_ps( a, _mm_min_ps( v, b ) );
}
Dalam fungsi seperti ini saya masih berpikir dalam hal instruksi mesin khusus , tetapi saya memiliki kemudahan untuk menuliskannya dalam C sehingga saya tidak perlu khawatir tentang pewarnaan register dan penjadwalan dan memuat ops dan detail membosankan lainnya.
Anda masih perlu mengetahui instruksi apa yang didukung CPU, terutama karena kompiler modern sangat buruk dalam mengkode kode, dibandingkan dengan seberapa baik manusia pintar dapat melakukan pekerjaan itu. Terkadang detail halus tentang bagaimana Anda mengatur kode Anda dapat memiliki implikasi besar untuk kinerja yang tidak jelas tanpa memahami apa yang dilakukan mesin.
Meskipun kami tidak dapat membuat kode dalam perakitan, kami masih banyak melakukan debug dalam perakitan. Mengoptimalkan kompiler secara agresif mengatur ulang kode dengan cara yang tidak bisa diikuti oleh para debugger, sehingga seringkali ketika men-debug "mode pelepasan" membangun hal terbaik untuk dilakukan adalah membuka pembongkaran dan menelusuri kode dengan cara itu. Pembicaraan GDC ini pada "Forensik Debugging" dari crash menggambarkan banyak dari mengapa dan bagaimana debug pada level itu.
Masalah yang biasanya membutuhkan perakitan linting tangan semakin sedikit jumlahnya. Apa yang Anda "mungkin" peroleh dalam kecepatan yang Anda kehilangan dalam keterbacaan dan kemampuan untuk debug. Itu juga harus dilakukan hanya sebagai salah satu langkah optimasi terakhir pada bagian kode karena dalam banyak kasus masalah kecepatan bukanlah sesuatu yang tidak dapat dibuat lebih baik dengan perakitan. Saat ini CPU telah menjadi jauh lebih cepat sementara kecepatan memori belum, seringkali lebih penting untuk mengontrol bagaimana data mengalir melalui CPU daripada yang lain.
Dengan kompiler modern, mereka juga merasa sulit untuk mengoptimalkan kode perakitan karena mereka harus berurusan dengan register apa pun yang telah Anda sentuh dan mereka biasanya tidak dapat memesan ulang instruksi dalam kode kerajinan tangan Anda. Untuk mengurangi kebutuhan perakitan, sekarang ada intrinsik yang membantu untuk mendapatkan akses ke konsep tingkat rendah, tetapi dengan cara yang ramah kompiler dan memungkinkan mereka untuk bekerja dengan Anda daripada menentang.
Dengan itu, SPU pada PS3 adalah salah satu area di mana orang masih harus menggunakan perakitan untuk mendapatkan hasil maksimal dari prosesor, dengan pipelining instruksi manual misalnya seperti yang dijelaskan di sini .
Faktanya adalah kita hidup di dunia multi platform, dan bagian dari kode permainan kita harus disesuaikan dengan platform lokal - yah tidak harus, tetapi ada manfaatnya jika kita mengambil keuntungan dari hal-hal perangkat keras lokal!
Ini bukan tentang permainan atau logika game, ini tentang lokalitas perangkat keras untuk kinerja optimal dari kode di mana logika permainan bergantung, kita memang dapat membungkus bagian kode, misalnya menggunakan makro, sehingga ada satu kode sumber, yang dijalankan dengan baik pada Platform itu dibangun melawan.