Ya, baik keselarasan dan pengaturan data Anda dapat membuat perbedaan besar dalam kinerja, bukan hanya beberapa persen tetapi beberapa hingga ratusan persen.
Ambil loop ini, dua instruksi penting jika Anda menjalankan loop cukup.
.globl ASMDELAY
ASMDELAY:
subs r0,r0,#1
bne ASMDELAY
bx lr
Dengan dan tanpa cache, dan dengan penyelarasan dengan dan tanpa cache melemparkan dalam prediksi cabang dan Anda dapat memvariasikan kedua instruksi kinerja dengan jumlah yang signifikan (kutu waktu):
min max difference
00016DDE 003E025D 003C947F
Tes kinerja yang sangat mudah Anda lakukan sendiri. menambah atau menghapus nops di sekitar kode yang sedang diuji dan melakukan pekerjaan waktu yang akurat, pindahkan instruksi yang sedang diuji di sepanjang rentang alamat yang cukup luas untuk menyentuh tepi garis cache, dll.
Hal yang sama dengan akses data. Beberapa arsitektur mengeluh tentang akses yang tidak selaras (melakukan pembacaan 32 bit di alamat 0x1001 misalnya), dengan memberi Anda kesalahan data. Beberapa di antaranya Anda dapat menonaktifkan kesalahan dan membuat hit kinerja. Orang lain yang memungkinkan akses yang tidak selaras Anda baru saja mendapatkan kinerja yang baik.
Kadang-kadang "instruksi" tetapi sebagian besar waktu adalah siklus jam / bus.
Lihatlah implementasi memcpy di gcc untuk berbagai target. Katakanlah Anda menyalin struktur yang 0x43 byte, Anda mungkin menemukan implementasi yang menyalin satu byte meninggalkan 0x42 kemudian menyalin 0x40 byte dalam potongan besar yang efisien maka 0x2 terakhir dapat dilakukan sebagai dua byte individu atau sebagai transfer 16 bit. Alignment dan target ikut berperan jika sumber dan alamat tujuan berada pada alignment yang sama katakan 0x1003 dan 0x2003, maka Anda bisa melakukan satu byte, kemudian 0x40 dalam potongan besar kemudian 0x2, tetapi jika satu adalah 0x1002 dan 0x1003 lainnya, maka sangat jelek dan sangat lambat.
Sebagian besar waktu adalah siklus bus. Atau lebih buruk jumlah transfer. Ambil prosesor dengan bus data selebar 64 bit, seperti ARM, dan lakukan transfer empat kata (baca atau tulis, LDM atau STM) di alamat 0x1004, itu adalah alamat yang selaras kata, dan legal, tetapi jika bus tersebut 64 lebar bit kemungkinan instruksi tunggal akan berubah menjadi tiga transfer dalam hal ini 32 bit pada 0x1004, 64 bit pada 0x1008 dan 32 bit pada 0x100A. Tetapi jika Anda memiliki instruksi yang sama tetapi pada alamat 0x1008 itu bisa melakukan transfer empat kata tunggal di alamat 0x1008. Setiap transfer memiliki waktu setup yang terkait. Jadi perbedaan alamat 0x1004 hingga 0x1008 dengan sendirinya bisa beberapa kali lebih cepat, bahkan / esp saat menggunakan cache dan semua adalah hit cache.
Omong-omong, bahkan jika Anda membaca dua kata di alamat 0x1000 vs 0x0FFC, 0x0FFC dengan misses cache akan menyebabkan dua baris cache membaca di mana 0x1000 adalah satu baris cache, Anda mendapat penalti dari garis cache dibaca tetap untuk acak akses (membaca lebih banyak data daripada menggunakan) tetapi kemudian dua kali lipat. Bagaimana struktur Anda disejajarkan atau data Anda secara umum dan frekuensi Anda mengakses data itu, dll, dapat menyebabkan penumpukan cache.
Anda dapat menghapus data Anda sehingga saat Anda memproses data yang dapat Anda buat penggusuran, Anda bisa benar-benar tidak beruntung dan hanya menggunakan sebagian kecil dari cache Anda dan ketika Anda melompati gumpalan data berikutnya bertabrakan dengan gumpalan sebelumnya . Dengan mencampur data Anda atau mengatur ulang fungsi dalam kode sumber, dll Anda dapat membuat atau menghapus tabrakan, karena tidak semua cache dibuat sama dengan kompiler tidak akan membantu Anda di sini, itu ada pada Anda. Bahkan mendeteksi hit atau peningkatan kinerja ada pada Anda.
Semua hal yang telah kami tambahkan untuk meningkatkan kinerja, bus data yang lebih luas, jalur pipa, cache, prediksi cabang, beberapa unit / jalur eksekusi, dll. Paling sering akan membantu, tetapi semuanya memiliki titik lemah, yang dapat dieksploitasi baik secara sengaja atau tidak sengaja. Ada sangat sedikit kompiler atau pustaka dapat lakukan tentang hal itu, jika Anda tertarik pada kinerja yang Anda butuhkan untuk menyetel dan salah satu faktor penyetelan terbesar adalah keselarasan kode dan data, tidak hanya selaras pada 32, 64, 128, 256 batas bit, tetapi juga di mana hal-hal relatif satu sama lain, Anda ingin loop yang banyak digunakan atau data yang digunakan kembali untuk tidak mendarat dengan cara cache yang sama, mereka masing-masing menginginkannya sendiri. Compiler dapat membantu, misalnya memesan instruksi untuk arsitektur skalar super, mengatur ulang instruksi yang relatif satu sama lain, tidak masalah,
Pengawasan terbesar adalah asumsi bahwa prosesor adalah hambatan. Belum benar selama satu dekade atau lebih, memberi makan prosesor adalah masalah dan di situlah masalah seperti hit kinerja penyelarasan, meronta-ronta cache, dll ikut bermain. Dengan sedikit kerja bahkan pada tingkat kode sumber, mengatur ulang data dalam suatu struktur, memesan deklarasi variabel / struct, memesan fungsi dalam kode sumber, dan sedikit kode tambahan untuk menyelaraskan data, dapat meningkatkan kinerja beberapa kali lipat atau lebih.