Anda perlu tahu di mana harus meletakkan nol



Beberapa optimasi memerlukan struktur data yang kompleks dan ribuan baris kode. Dalam kasus lain, peningkatan produktivitas yang serius memberikan perubahan minimal: terkadang Anda hanya perlu menetapkan nol. Ini seperti kisah lama tentang seorang kapten yang tahu tempat yang tepat untuk memukul dengan palu, dan kemudian menagih klien: $ 0,50 untuk pukulan ke katup dan $ 999,50 untuk mengetahui ke mana harus memukul.

Saya pribadi menemui beberapa kesalahan kinerja yang diperbaiki dengan memasukkan nol, dan dalam artikel ini saya ingin berbagi dua cerita.

Pentingnya pengukuran


Pada masa Xbox asli, saya membantu mengoptimalkan banyak game. Di salah satu dari mereka, profiler menunjuk ke fungsi transformasi matriks, yang mengkonsumsi 7% dari waktu CPU - lompatan terbesar pada grafik. Jadi saya rajin bekerja untuk mengoptimalkan fitur ini.

Dapat dilihat bahwa saya bukan orang pertama yang mencoba melakukan ini. Fungsi ini telah ditulis ulang di assembler. Saya menemukan beberapa peningkatan potensial dalam bahasa assembly dan mencoba mengukur efeknya. Ini adalah langkah penting, jika tidak mudah untuk melakukan "optimasi", yang tidak akan mengubah apa pun atau bahkan memperburuk situasi.

Namun, pengukurannya sulit. Saya menjalankan permainan, bermain sedikit dengan profil paralel, dan kemudian mempelajari profil: apakah kode semakin cepat. Tampaknya ada sedikit peningkatan, tetapi tidak mungkin untuk mengatakan dengan pasti.

Jadi saya menerapkan metode ilmiah . Dia menulis kumpulan tes untuk mengelola versi kode lama dan baru untuk secara akurat mengukur perbedaan kinerja. Ini tidak memakan banyak waktu: seperti yang diharapkan, kode baru sekitar 10% lebih cepat daripada yang lama.

Tetapi ternyata akselerasi 10% tidak masuk akal.

Jauh lebih menarik bahwa di dalam kode uji dieksekusi sekitar 10 kali lebih cepat daripada dalam permainan. Ini adalah penemuan yang menarik.

Setelah memeriksa hasilnya, saya melihat ke dalam kekosongan untuk sementara waktu, tetapi kemudian saya sadar.

Peran caching


Untuk memberikan kontrol penuh dan kinerja maksimum kepada pengembang game, konsol game memungkinkan Anda mengalokasikan memori dengan berbagai atribut. Secara khusus, Xbox asli memungkinkan Anda untuk mengalokasikan memori yang tidak dapat di-cache. Jenis memori ini (sebenarnya, jenis tag di tabel halaman) berguna saat menulis data ke GPU. Karena memori tidak di-cache, penulisan akan langsung masuk ke RAM tanpa penundaan atau kontaminasi cache dengan pemetaan "normal".

Dengan demikian, memori yang tidak di-cache adalah optimasi yang penting, tetapi harus digunakan dengan hati-hati. Khususnya, sangat penting bahwa gim tidak pernah mencoba membaca dari memori yang tidak di-cache, jika tidak kinerjanya akan menurun. Bahkan CPU 733 MHz yang relatif lambat di Xbox asli memerlukan cache sendiri untuk memberikan kinerja membaca yang cukup.

Sekarang menjadi jelas apa yang terjadi. Rupanya, untuk fungsi ini, data dialokasikan dalam memori non-cache, sehingga kinerjanya rendah. Sebuah tes kecil mengkonfirmasi hipotesis ini, jadi inilah saatnya untuk memperbaiki masalahnya. Saya menemukan garis di mana memori dialokasikan, klik dua kali pada nilai bendera, dan menunjuk ke nol.

Alih-alih sekitar 7% dari waktu prosesor, fungsi mulai mengkonsumsi sekitar 0,7% dan tidak lagi menjadi masalah.

Pada akhir minggu, laporan saya terlihat seperti ini: "39,999 jam penelitian, 0,001 jam pemrograman adalah sukses besar!"

Pengembang biasanya tidak perlu khawatir tentang mengalokasikan memori non-cache secara tidak sengaja: pada sebagian besar sistem operasi, opsi ini tidak tersedia di ruang pengguna menggunakan metode standar. Tetapi jika Anda tertarik pada seberapa banyak memori yang tidak dapat disimpan dalam cache dapat memperlambat program, coba tanda PAGE_NOCACHE atau PAGE_WRITECOMBINE di VirtualAlloc .

0 GiB lebih baik dari 4 GiB


Saya ingin menceritakan kisah lain kepada Anda. Ini tentang bug yang saya temukan, dan orang lain memperbaikinya. Beberapa tahun yang lalu, saya perhatikan bahwa cache disk di laptop saya terlalu sering dihapus. Saya melacak bahwa ini terjadi ketika jalur 4 GiB tercapai, dan pada akhirnya ternyata driver untuk HDD cadangan baru saya menyetel SectorSize ke 0xFFFFFFFF (atau −1) ketika menunjuk ke ukuran sektor yang tidak diketahui. Kernel Windows menafsirkan nilai ini sebagai 4 GiB dan mengalokasikan blok memori yang sesuai, yang menyebabkan masalah.

Saya tidak memiliki kontak di Western Digital, tetapi saya dapat dengan aman berasumsi bahwa mereka memperbaiki kesalahan ini dengan mengganti 0xFFFFFFFF konstan (atau −1) dengan nol. Satu karakter dimasukkan - dan menyelesaikan masalah kinerja yang serius.

(Baca lebih lanjut tentang studi ini dalam artikel "Memperlambat Windows: Menjelajahi dan Mengidentifikasi" )

Pengamatan


  • Dalam kedua kasus, masalahnya adalah dengan caching
  • Yang menentukan adalah penggunaan profiler untuk menunjukkan masalah.
  • Jika tambalan tidak diverifikasi oleh pengukuran, maka itu tidak akan membantu.
  • Saya bisa menulis tentang banyak kasus lain seperti itu, tetapi mereka terlalu rahasia atau terlalu membosankan.
  • Keputusan yang tepat tidak harus rumit. Terkadang peningkatan besar memberi perubahan kecil. Yang perlu Anda ketahui adalah di mana

Saya kebetulan mengoptimalkan kode dengan membatalkan komentar #define dan perubahan sepele lainnya. Ceritakan pada kami jika Anda memiliki cerita seperti itu.

Source: https://habr.com/ru/post/id434056/


All Articles