- Koheren cache memastikan semua salinan data yang sama dalam cache yang berbeza dan dalam RAM kekal konsisten pada sistem berbilang teras.
- Hierarki cache dengan tahap terakhir yang dikongsi memudahkan kawalan konsistensi dan mengurangkan akses langsung ke memori utama.
- Protokol koheren menggunakan strategi pembatalan salinan atau kemas kini, disokong oleh keadaan dan bit kawalan setiap baris cache.
- Pengkompil dan sistem pengendalian boleh menambah konsistensi perkakasan dengan memasukkan arahan dan mengkonfigurasi memori untuk tempoh kritikal.

Apabila anda melihat gambar rajah mana-mana pemproses berbilang teras moden, corak yang sama sentiasa muncul: berbilang teras, setiap satu dengan cache berdekatannya sendiri, dan cache peringkat terakhir yang dikongsi yang bertindak sebagai titik sepunya sebelum mencapai RAM. Susunan ini bukanlah secara tidak sengaja atau sekadar kehendak pereka, tetapi merupakan tindak balas langsung kepada masalah kritikal dalam sistem selari: kekoherenan cache.
Tanpa mekanisme konsistensi yang mantap, setiap teras boleh berfungsi dengan versi data yang sama dalam memori yang berbeza dan ketinggalan zaman , yang dalam program dunia sebenar diterjemahkan kepada ralat halus, kegagalan yang tidak dapat diramalkan, malah ranap sistem. Oleh itu, memahami bagaimana konsistensi ini dikekalkan—pada peringkat perkakasan dan perisian—adalah kunci untuk memahami prestasi dan kestabilan CPU berbilang teras moden.
Apakah itu koheren cache: metafora terminal
Bayangkan beberapa orang duduk di hadapan terminal yang berbeza, semuanya mengedit dokumen yang sama yang disimpan di pelayan pusat . Setiap skrin memaparkan salinan fail dan sebarang perubahan yang dibuat oleh seseorang dijangka akan tercermin serta-merta pada skrin orang lain.
Agar ini berfungsi, perlu ada mekanisme penyegerakan yang menyebarkan perubahan dokumen ke semua terminal, supaya semua orang sentiasa melihat versi yang sama. Selagi sistem ini berfungsi, semuanya baik-baik saja: sesiapa yang mengubah suai teks tahu bahawa orang lain akan melihat versi baharu hampir serta-merta.
Sekarang bayangkan sistem penyegerakan tiba-tiba gagal. Setiap orang terus mengedit, yakin mereka sedang mengusahakan dokumen yang dikongsi, tetapi pada hakikatnya, setiap terminal dibiarkan dengan salinan setempatnya sendiri yang terputus sambungan . Mulai saat itu, perubahan yang dibuat oleh seorang tidak sampai kepada orang lain, dan dokumen itu mula menyimpang tanpa kawalan.
Dalam bidang pengkomputeran, inilah yang akan berlaku jika CPU kekurangan protokol konsistensi yang boleh dipercayai: satu teras mengubah suai data dalam memori, tetapi teras yang lain terus membaca versi lama daripada cache peribadi mereka . Ini mewujudkan keadaan subur untuk ralat logik yang serius, data yang rosak dan tingkah laku penyahpepijatan.
Oleh itu, koheren cache merupakan satu set mekanisme yang memastikan bahawa, dalam sistem berbilang teras, semua salinan data yang sama yang diedarkan merentasi cache dan RAM yang berbeza mengekalkan keadaan yang konsisten . Walaupun terdapat berbilang salinan, sistem mesti bertindak "seolah-olah" hanya ada satu.

Hierarki cache dan memori dalam CPU berbilang teras
Cache CPU ialah memori kecil yang sangat pantas yang menyimpan salinan ketulan RAM yang kerap digunakan . Apabila pemproses melaksanakan kod, bukannya mengakses RAM (yang agak perlahan) secara berterusan, ia cuba membaca dan menulis ke cache, sekali gus mengurangkan kependaman secara drastik.
Caranya, sudah tentu, ialah cache tidak menyimpan "versi rasmi" data, tetapi hanya replika sementara . Mengikuti metafora terminal, RAM akan menjadi dokumen pada pelayan, manakala cache akan menjadi skrin setempat yang memaparkan salinan bahagian tertentu fail.
Dalam CPU berbilang teras, reka bentuk menjadi lebih kompleks kerana setiap teras biasanya mempunyai cache Tahap 1 (L1) dan juga Tahap 2 (L2) peribadinya sendiri . Di atasnya, cache Tahap 3 yang dikongsi (contohnya) ditambah, terletak di antara teras dan pengawal memori yang menyediakan akses kepada RAM.
Cache kongsi ini diperkenalkan kerana membenarkan semua teras mengakses RAM secara langsung dan intensif akan menyebabkan konflik akses, pertikaian pada bas memori dan penurunan prestasi yang ketara . Cache peringkat terakhir bertindak sebagai "penimbal" biasa yang mengurangkan akses RAM dan memusatkan sebahagian besar trafik data.
Tambahan pula, banyak seni bina mengatur cache secara inklusif: baris yang disimpan dalam tahap yang berhampiran dengan pemproses juga terdapat dalam tahap hierarki yang lebih tinggi . Iaitu, baris yang muncul dalam L1 juga berada dalam L2 dan, seterusnya, dalam L3. Ini mempunyai akibat yang sangat berguna untuk konsistensi: hanya mengemas kini cache tahap terendah dengan betul sudah cukup untuk mengawal keadaan tahap lain tanpa perlu sentiasa mengakses RAM.
Mengapakah caching kongsian peringkat terakhir adalah kunci kepada konsistensi
Tanpa cache peringkat terakhir global ini, setiap teras perlu menyemak konsistensi secara langsung terhadap memori utama . Setiap kali baris memori dalam cache peribadi diubah suai, adalah perlu untuk menyemak sama ada teras lain mengekalkan salinan baris yang sama dan, jika ya, mengemas kini atau membatalkannya di mana-mana sahaja.
Dalam sistem yang mempunyai banyak teras, beban kerja pemeriksaan ini akan mengakibatkan sejumlah besar transaksi ke RAM , sekali gus menafikan banyak manfaat mempunyai cache yang pantas. Dengan meletakkan cache yang dikongsi antara teras dan memori, CPU boleh menumpukan kawalan koheren di satu lokasi perantaraan.
Dalam banyak pelaksanaan, cache pada tahap yang lebih tinggi (lebih jauh dari pemproses) mengandungi salinan baris yang terdapat pada tahap yang lebih dekat dengan teras . Dengan organisasi ini, protokol koheren hanya perlu memastikan bahawa tahap terakhir disegerakkan dengan memori utama dan tahap peribadi setiap teras disegerakkan dengan tahap yang betul-betul di atasnya.
Ini boleh digambarkan sebagai sejenis anak patung bersarang Rusia: cache peringkat ketiga merangkumi kandungan peringkat kedua dan pertama , peringkat kedua merangkumi kandungannya sendiri dan kandungan peringkat pertama, dan peringkat pertama hanya mengetahui garisannya sendiri. Oleh itu, dengan mengawal "anak patung besar" (peringkat terakhir), sistem dapat menyelaraskan yang lain dengan lebih cekap.
Hasilnya ialah mengekalkan konsistensi menjadi lebih menjimatkan dari segi reka bentuk dan trafik memori . Daripada memaksa setiap teras untuk sentiasa berurusan dengan RAM, protokol ini beroperasi pada cache kongsi dan dari situ menguruskan baris mana yang harus dikemas kini atau dibatalkan dalam cache peribadi.
Kaedah kemas kini: pembatalan dan pengemaskinian salinan
Isu kritikal timbul apabila dua atau lebih teras ingin mengakses, hampir serentak, barisan data yang sama yang direplikasi merentasi berbilang cache . Dalam konteks ini, sistem konsistensi biasanya menggunakan dua strategi asas semasa mengendalikan penulisan.
Kaedah pertama adalah berdasarkan pembatalan. Apabila kernel perlu menulis ke baris cache tertentu, protokol tersebut akan membatalkan sebarang salinan baris yang sama yang mungkin wujud dalam cache lain . Hanya kernel yang akan menulis sahaja yang memastikan baris tersebut dalam keadaan didayakan baca dan tulis; kernel yang lain, jika mereka mahu menggunakan data tersebut sekali lagi, perlu memuatkan semula baris tersebut dari peringkat yang lebih tinggi (atau dari memori) dengan versi terkini.
Strategi kedua melibatkan pengemaskinian. Dalam kes ini, apabila kernel mengubah suai baris, sistem akan cuba menyebarkan kandungan baharu secara automatik ke salinan sedia ada dalam cache lain . Dengan cara ini, semua cache yang menyimpan baris tersebut menerima versi terkini tanpa perlu membatalkan dan memuatkannya semula kemudian.
Setiap pendekatan mempunyai kebaikan dan keburukannya. Penyahsahian biasanya lebih cekap apabila penulisan kerap dilakukan kerana ia mengelakkan sistem memori tepu dengan kemas kini yang mungkin tidak diperlukan oleh teras lain dengan segera. Sebaliknya, pengemaskinian boleh memberi kelebihan apabila banyak teras kerap membaca data yang sama yang diubah suai secara agak jarang , kerana ia mengurangkan kependaman dengan tidak perlu memuatkan semula baris selepas setiap pembatalan.
Dalam kedua-dua kes, kedua-dua kaedah menggunakan keadaan tambahan dan bit kawalan dalam baris cache. Setiap baris biasanya merangkumi maklumat tentang sama ada kandungannya sepadan dengan kandungan dalam RAM , dan sama ada ia dikongsi, diubah suai, eksklusif, dikhaskan, dsb., bergantung pada protokol tertentu (MESI, MOESI, MSI, dsb.). Ini membolehkan perkakasan membuat keputusan pantas tentang apa yang perlu dilakukan apabila operasi baca atau tulis berlaku pada baris yang telah direplikasi.
Memeriksa konsistensi antara cache dan memori
Mengesahkan secara langsung keseragaman antara semua tahap cache CPU atau GPU dan memori utama akan menjadi tugas yang besar, baik dari segi kerumitan reka bentuk mahupun kos prestasi. Oleh itu, sistem moden mengatur pengesahan ini secara hierarki.
Cache yang paling dekat dengan pemproses (L1, L2) biasanya tidak disambungkan terus ke RAM, tetapi ke tahap cache seterusnya. Ini bermakna konsistensi tidak disahkan terhadap memori utama pada setiap tahap, tetapi sebaliknya terhadap tahap yang lebih tinggi . Ini mengurangkan bilangan akses RAM dan memudahkan logik yang diperlukan pada tahap yang lebih rendah.
Akhirnya, perbandingan antara kandungan cache dan kandungan RAM dilakukan antara cache peringkat terakhir dan memori utama . Jika peringkat terakhir ini mengekalkan keadaan yang betul dan konsisten, dan setiap peringkat yang lebih rendah mengekalkan konsistensinya dengan yang di atasnya, keseluruhan hierarki kekal konsisten tanpa perlu menyemak setiap baris terhadap RAM berulang kali.
Apabila kernel menulis ke baris cache dan mengubah datanya, keadaan baris tersebut ditanda untuk menunjukkan bahawa ia tidak lagi sepadan dengan salinan yang disimpan dalam memori . Dari situ, protokol menyelaras kemas kini: ia menandakan salinan yang sepadan dalam cache lain sebagai dikhaskan atau tidak sah dan, apabila sesuai, menulis kandungan baharu ke baris memori utama yang berkaitan.
Organisasi bertingkat ini membolehkan perubahan merebak secara progresif dari kernel, yang mengemas kini data, ke memori utama, melalui setiap peringkat cache dengan cara yang terkawal. Dengan cara ini, mengekalkan konsistensi tidak menjadi kesesakan yang tidak dapat diatasi untuk pemproses.
Koheren perkakasan lawan koheren perisian
Setakat ini kita telah membincangkan mekanisme konsistensi yang kebanyakannya dilaksanakan dalam perkakasan: protokol, bit status, cache kongsi, dan sebagainya. Walau bagaimanapun, terdapat pendekatan lain yang bertujuan untuk mengalihkan sebahagian daripada kerumitan tersebut kepada perisian , khususnya kepada pengkompil dan sistem pengendalian.
Skim konsistensi berasaskan perisian cuba mengurangkan keperluan untuk logik atas cip tambahan dengan menganalisis kod dan membuat keputusan masa kompilasi . Ideanya ialah jika pengkompil boleh menyimpulkan bila dan bagaimana data kongsi tertentu diakses, ia boleh, dalam banyak kes, menghalang data tersebut daripada disimpan dalam cache atau mengurus keterlihatannya secara eksplisit.
Pendekatan ini mempunyai kelebihan yang jelas: sebahagian daripada beban kerja beralih daripada masa jalan kepada penyelesaian masa kompilasi . Pengkompil cuba menjangka dan menjana kod yang mengelakkan situasi berbahaya daripada mengesan dan mengendalikan semua konflik secara tiba-tiba, dan bukannya perkakasan yang mengesan dan mengendalikan semua konflik.
Kelemahannya ialah analisis kod statik adalah terhad, dan oleh itu pengkompil cenderung untuk bersikap konservatif . Ini bermakna, untuk mengelakkan pelanggaran konsistensi, mereka sering membuat keputusan yang mengurangkan keberkesanan cache. Jika mereka mengesyaki bahawa sesetengah data mungkin bermasalah, mereka kerap menghalangnya daripada disimpan dalam cache atau memaksa penyegerakan lebih kerap daripada yang diperlukan.
Oleh itu, walaupun skema perisian ini menarik secara teori, terutamanya untuk memudahkan reka bentuk perkakasan, dalam praktiknya ia tidak menggantikan sokongan koheren yang disepadukan ke dalam CPU itu sendiri , tetapi sebaliknya melengkapinya dalam beberapa senario tertentu.
Peranan pengkompil dalam konsistensi cache
Satu elemen penting dalam pendekatan konsistensi berasaskan perisian ialah peranan pengkompil. Pengkompil boleh melakukan analisis mendalam terhadap kod dan menentukan struktur data kongsi yang mungkin tidak selamat untuk penyimpanan caching . Berdasarkan ini, ia menandakan elemen-elemen ini dengan cara khas atau menyesuaikan penjanaan kod.
Pendekatan yang paling mudah, dan juga paling konservatif, adalah untuk menghalang pembolehubah data kongsi daripada disimpan dalam cache . Iaitu, setiap akses kepada pembolehubah ini memaksa akses kepada memori utama atau kawasan yang tidak boleh disimpan dalam cache. Ini menjamin konsistensi, tetapi terlepas banyak peluang prestasi, kerana struktur kongsi sebenarnya boleh digunakan secara peribadi semasa tempoh tertentu, atau baca sahaja pada tempoh lain.
Pada hakikatnya, masalah konsistensi hanya timbul semasa selang masa apabila sekurang-kurangnya satu proses boleh menulis kepada pembolehubah dan proses lain boleh membacanya . Di luar tempoh kritikal ini, pembolehubah boleh dianggap sebagai untuk kegunaan eksklusif satu thread atau sebagai pemalar berkesan untuk seketika, membolehkannya disimpan dalam cache tanpa masalah.
Strategi kompilasi yang paling canggih cuba mengenal pasti tempoh "selamat" di mana pembolehubah yang dikongsi boleh dianggap tidak bercanggah . Untuk melakukan ini, pengkompil menganalisis laluan pelaksanaan, akses serentak yang berpotensi dan corak penyegerakan (kunci, bahagian kritikal, dll.). Berdasarkan analisis ini, ia membahagikan hayat pembolehubah kepada fasa: ada yang sesuai untuk penyimpanan caching, ada yang memerlukan pengendalian khas.
Semasa tempoh kritikal, apabila akses serentak dengan penulisan dikesan, pengkompil memasukkan arahan tambahan ke dalam kod yang dijana untuk menguatkuasakan konsistensi cache . Arahan ini mungkin memaksa penyingkiran cache, muat semula memori, halangan memori atau akses ke kawasan yang ditanda sebagai tidak boleh di-cache, bergantung pada model pengaturcaraan dan seni bina asas.
Hubungan antara pengkompil, sistem pengendalian dan perkakasan
Ungkapan "pengkompil memasukkan arahan ke dalam kod yang dijana untuk menguatkuasakan ketekalan cache" mungkin menyebabkan seseorang berfikir bahawa sistem pengendalian membaca arahan ini seolah-olah ia adalah petunjuk peringkat tinggi dan, berdasarkan itu, memutuskan cara melaksanakan program tersebut. Pada hakikatnya, mekanismenya agak berbeza.
Apabila pengkompil menambah jenis arahan ini, apa yang diperkenalkan ke dalam binari ialah operasi khusus yang disokong oleh seni bina atau persekitaran masa jalan . Contohnya, ia boleh memasukkan arahan pembilasan cache, halangan memori, arahan khas untuk menandakan kawasan sebagai tidak boleh di-cache atau panggilan kepada perkhidmatan sistem pengendalian yang mengkonfigurasi atribut memori.
Sistem pengendalian tidak mentafsirkan arahan ini sebagai "komen" atau "petunjuk" peringkat tinggi yang ditulis oleh pengkompil; ia hanya melaksanakan kod mesin seperti yang lain . Walau bagaimanapun, sebahagian daripada arahan ini direka bentuk untuk berinteraksi dengan subsistem memori dan pengurusan cache, sekali gus mengubah cara CPU mengakses data tertentu.
Dalam erti kata lain, pengkompil menjalankan analisis awal dan menjana kod yang, apabila dilaksanakan, menghasilkan tingkah laku cache yang diingini . Sistem pengendalian bekerjasama dengan mewujudkan atribut memori (kawasan boleh cache atau tidak boleh cache, dasar penulisan, dsb.) dan menyediakan primitif penyegerakan, tetapi ia bukan "membaca" arahan khas dalam erti kata mentafsirkannya secara semantik seperti yang dilakukan oleh pengkompil.
Ia juga boleh berlaku bahawa perkakasan, setelah melihat arahan tertentu, mengaktifkan mekanisme koheren atau penyegerakan tertentu . Contohnya, arahan pagar atau penghalang menjamin susunan akses memori dan menguatkuasakan kesan keterlihatan tertentu merentasi hierarki cache. Dalam kes ini, terdapat kerjasama tiga hala: pengkompil memutuskan di mana hendak meletakkan arahan ini, sistem pengendalian mengkonfigurasi persekitaran pelaksanaan dan perkakasan melaksanakan tingkah laku sebenar pada peringkat cache dan bas memori.
Bersama-sama, semua elemen ini memastikan bahawa, walaupun dengan berbilang salinan data yang sama diagihkan merentasi cache dan memori utama yang berbeza, program selari dijalankan dengan model memori yang konsisten . Koheren cache, jauh daripada menjadi perincian CPU dalaman yang mudah, menjadi komponen utama untuk sistem berbilang teras beroperasi dengan andal dan cekap.
Memahami bagaimana hierarki cache, protokol koheren perkakasan dan teknik sokongan perisian digabungkan menjadikannya lebih jelas mengapa reka bentuk CPU moden berkongsi struktur yang serupa dan mengapa kegagalan kecil dalam mana-mana mekanisme tersebut boleh mencetuskan tingkah laku huru-hara dalam aplikasi serentak yang bergantung sepenuhnya pada semua teras melihat data yang sama pada masa yang tepat.