Ketika CPU dengan cache L1 melakukan penulisan, yang biasanya terjadi adalah (dengan asumsi bahwa baris cache yang sedang ditulisnya sudah ada dalam cache L1) cache (selain memperbarui data) menandai bahwa garis cache sebagai kotor , dan akan menulis garis keluar dengan data yang diperbarui di beberapa waktu kemudian.
Salah satu optimasi yang mungkin dilakukan adalah membuat cache membandingkan konten penulisan dan isi cache sebelumnya, dan jika keduanya sama, jangan tandai baris sebagai kotor. Karena ini memungkinkan cache untuk menghindari write-backs sesekali, saya dapat melihat bagaimana produsen CPU melihat ini sepadan dengan gerbang yang diperlukan untuk melakukan logika ini.
Pertanyaan saya: apakah ada CPU yang melakukan optimasi ini?
Latar belakang mengapa saya bertanya: Saya sedang menulis beberapa kode yang perlu memiliki akses memori yang konstan; yaitu, seseorang yang dapat mendengarkan perilaku cache seharusnya tidak dapat menyimpulkan apa yang saya lakukan. Beberapa akses saya adalah menulis, dan dengan cara yang jelas untuk menerapkan kode ini, banyak penulisan akan menulis data yang sama yang sudah ada di sana. Saya perlu melakukan penulisan karena, tergantung pada data, data yang saya tulis mungkin sama atau tidak sama, dan penting untuk melakukan tindakan yang sama. Jika CPU mengoptimalkan dengan tidak benar-benar menulis 'tidak ada perubahan-tulis', itu berarti bahwa perilaku cache akan bervariasi tergantung pada apa yang saya lakukan, yang akan menumbangkan tujuan saya.
Jadi, adakah CPU yang mencoba mengoptimalkan penulisan dengan cara ini?
Jawaban:
Dari jam pencarian, saya tidak dapat menemukan CPU yang menggunakan optimasi khusus ini. Sebagian besar optimasi yang disebutkan biasanya terkait dengan hit / miss dengan operasi baca / tulis dan akses data:
(halaman 7 dan) https://cseweb.ucsd.edu/classes/fa14/cse240A-a/pdf/08/CSE240A-MBT-L15-Cache.ppt.pdf
Namun, itu tidak berarti bahwa optimasi ini tidak dapat dilakukan. Secara umum, dimungkinkan untuk secara program mengakses ukuran garis cache CPU. Dimungkinkan juga untuk mengakses nilai saat ini di register cache - tetapi agak berbahaya untuk melakukannya. Jika Anda mengakses register yang salah pada waktu yang buruk, Anda bisa merusak yang terkait dengan program yang sedang berjalan. Atau Anda dapat secara tidak sengaja memodifikasi konten dari baris yang Anda coba baca.
Memperoleh nilai saat ini dalam cache register
Selain itu, semua solusi teoritis memerlukan beberapa bentuk implementasi perangkat lunak (assembler). Yang paling dekat yang saya temukan berkaitan dengan arsitektur ARM, yang muncul untuk memungkinkan manipulasi cache. Selain itu, Anda juga perlu mengetahui ukuran garis cache untuk CPU yang Anda inginkan. Anda dapat dengan hati-hati membaca konten cache ke lokasi sekunder dalam memori, dalam penambahan ukuran garis, dan membandingkannya dengan data yang akan ditulis ke register (atau jalur cache L1, dalam kasus ini).
Baca konten cache CPU
Dari sana, Anda dapat menyusun sistem berbasis perangkat lunak yang mencegah penulisan ulang yang identik. Meskipun ini sedikit disederhanakan, itu karena solusi harus berlaku untuk setiap CPU yang ada.
Kemungkinan lain yang saya temukan terkait dengan koherensi Cache:
Bagian yang relevan dari artikel Wikipedia tentang acche coherence
Poin utama yang menarik perhatian saya, sehubungan dengan masalah ini, adalah deskripsi Snarfing:
Dengan kata lain, mungkin ada mekanisme yang sudah ada. Hanya saja mereka mungkin tidak digunakan untuk optimasi yang Anda sarankan. Anda harus mengimplementasikan perangkat lunak yang melakukan perbandingan baca / tulis.
sumber
if (mem != x) { mem = x; }
bukanmem = x;
. Ini hanya kadang-kadang optimasi untuk garis cache bersama dalam program multi-utas, karena menulis mengganggu pembacaan utas lainnya.Menulis ke cache L1 adalah operasi yang sangat, sangat kritis.
Menulis kembali data yang sama persis agak jarang. Optimasi yang mempercepat dalam kasus khusus ini tidak akan mendapatkan banyak peningkatan total.
Di sisi lain, optimasi ini memerlukan perbandingan data lama dan data baru pada setiap penulisan ke memori cache. Yang membuat ini lebih buruk, adalah bahwa data yang ditulis harus benar-benar tersedia pada saat penulisan!
Itu biasanya tidak terjadi pada CPU modern. Data yang akan ditulis mungkin masih dihitung misalnya. Cache masih dapat melanjutkan, memuat garis cache jika perlu, menandai garis cache sebagai telah dimodifikasi dan seterusnya, bahkan sebelum perhitungan selesai. Semua pembukuan sudah dapat dilakukan kecuali untuk modifikasi baris cache yang sebenarnya. Jika Anda ingin membandingkan hasil yang baru ditulis dan data jalur cache lama, itu tidak mungkin.
Sebagai contoh, jika Anda memiliki kode C a [i] = x / y; divisi x / y membutuhkan waktu yang sangat lama untuk bekerja pada kebanyakan CPU. Namun, sebagian besar pekerjaan yang diperlukan untuk menangani menyimpan hasil ke [i] telah terjadi jauh sebelum divisi selesai; satu-satunya hal yang hilang adalah perpindahan delapan byte hasil ke baris cache. Operasi pembilasan garis cache akan secara otomatis menunggu sampai pembagian selesai. Operasi yang membaca [i] kemungkinan akan diarahkan untuk mendapatkan hasil langsung dari pembagi.
sumber
Tidak akankah optimasi seperti itu menggandakan waktu yang dibutuhkan CPU untuk menulis sesuatu ke dalam cache? Karena setiap baris cache menulis sekarang akan disertai dengan operasi perbandingan, yang tidak gratis.
Jadi, sebenarnya optimasi sekarang akan tergantung pada faktor yang sangat samar: berapa kali rata-rata perangkat lunak menulis ulang memori yang dapat di-cache dengan data yang sama.
sumber