Koherensi cache pada CPU multi-core: bagaimana cara menjaganya dan siapa yang mengontrolnya

Pembaharuan Terakhir: 6 March 2026
  • Koherensi cache memastikan bahwa semua salinan data yang sama di cache yang berbeda dan di RAM tetap konsisten pada sistem multi-core.
  • Hierarki cache dengan level terakhir yang digunakan bersama menyederhanakan kontrol konsistensi dan mengurangi akses langsung ke memori utama.
  • Protokol koherensi menggunakan strategi pembatalan salinan atau pembaruan, yang didukung oleh status dan bit kontrol per baris cache.
  • Kompiler dan sistem operasi dapat melengkapi konsistensi perangkat keras dengan menyisipkan instruksi dan mengkonfigurasi memori untuk periode-periode kritis.

Skema koherensi cache CPU

Ketika Anda melihat diagram prosesor multi-core modern mana pun, pola yang sama selalu muncul: beberapa core, masing-masing dengan cache terdekatnya sendiri, dan cache tingkat terakhir bersama yang bertindak sebagai titik umum sebelum mencapai RAM. Pengaturan ini bukanlah kebetulan atau keinginan para perancang, tetapi respons langsung terhadap masalah kritis dalam sistem paralel: koherensi cache.

Tanpa mekanisme konsistensi yang kuat, setiap inti prosesor dapat berakhir bekerja dengan versi data yang berbeda dan usang di memori , yang dalam program dunia nyata dapat menyebabkan kesalahan kecil, kegagalan yang tidak terduga, dan bahkan kerusakan sistem. Oleh karena itu, memahami bagaimana konsistensi ini dipertahankan—baik pada tingkat perangkat keras maupun perangkat lunak—adalah kunci untuk memahami kinerja dan stabilitas CPU multi-inti modern.

Apa itu koherensi cache: metafora terminal

waktu nyata dalam sistem elektronik
Artikel terkait:
Sistem elektronik waktu nyata: dasar-dasar, perencanaan, dan aplikasi

Bayangkan beberapa orang duduk di depan terminal yang berbeda, semuanya mengedit dokumen yang sama yang tersimpan di server pusat . Setiap layar menampilkan salinan file tersebut, dan setiap perubahan yang dilakukan oleh satu orang diharapkan segera tercermin di layar orang lain.

Agar hal ini berfungsi, perlu ada mekanisme sinkronisasi yang menyebarkan perubahan dokumen ke semua terminal, sehingga semua orang selalu melihat versi yang sama. Selama sistem ini berfungsi, semuanya akan baik-baik saja: siapa pun yang memodifikasi teks tahu bahwa orang lain akan melihat versi baru hampir secara instan.

Sekarang bayangkan sistem sinkronisasi tiba-tiba gagal. Setiap orang terus mengedit, yakin bahwa mereka sedang mengerjakan dokumen bersama, tetapi pada kenyataannya, setiap terminal hanya memiliki salinan lokalnya sendiri yang terputus . Sejak saat itu, perubahan yang dilakukan oleh satu orang tidak sampai ke orang lain, dan dokumen mulai menyimpang tanpa terkendali.

Dalam dunia komputasi, inilah yang akan terjadi jika CPU tidak memiliki protokol konsistensi yang andal: satu inti memodifikasi data dalam memori, tetapi inti lainnya terus membaca versi yang lebih lama dari cache pribadi mereka . Hal ini menciptakan lahan subur bagi kesalahan logika serius, data yang rusak, dan perilaku yang sulit di-debug.

Oleh karena itu, koherensi cache adalah serangkaian mekanisme yang memastikan bahwa, dalam sistem multi-core, semua salinan data yang sama yang didistribusikan di berbagai cache dan RAM mempertahankan keadaan yang konsisten . Bahkan jika terdapat beberapa salinan, sistem harus berperilaku "seolah-olah" hanya ada satu salinan.

Hierarki cache pada CPU multi-core

Cache dan hierarki memori pada CPU multi-core

Cache CPU adalah memori kecil dan sangat cepat yang menyimpan salinan bagian RAM yang sering digunakan . Ketika prosesor mengeksekusi kode, alih-alih terus-menerus mengakses RAM (yang relatif lambat), ia mencoba membaca dan menulis ke cache, sehingga mengurangi latensi secara drastis.

Triknya, tentu saja, adalah bahwa cache tidak menyimpan "versi resmi" data, tetapi hanya replika sementara . Mengikuti metafora terminal, RAM akan menjadi dokumen di server, sedangkan cache akan menjadi layar lokal yang menampilkan salinan bagian-bagian tertentu dari file tersebut.

Pada CPU multi-core, desainnya menjadi lebih kompleks karena setiap core biasanya memiliki cache Level 1 (L1) dan bahkan Level 2 (L2) pribadinya sendiri . Di atasnya, ditambahkan cache Level 3 bersama (misalnya), yang terletak di antara core dan pengontrol memori yang menyediakan akses ke RAM.

Cache bersama ini diperkenalkan karena mengizinkan semua inti prosesor untuk mengakses RAM secara langsung dan intensif akan menyebabkan konflik akses, perebutan pada bus memori, dan penurunan kinerja yang signifikan . Cache tingkat terakhir bertindak sebagai "buffer" umum yang mengurangi akses RAM dan memusatkan sebagian besar lalu lintas data.

  PC dengan kecerdasan buatan: perbedaan nyata dibandingkan dengan PC tradisional

Selain itu, banyak arsitektur mengatur cache secara inklusif: baris yang disimpan di level yang dekat dengan prosesor juga ada di level yang lebih tinggi dalam hierarki . Artinya, baris yang muncul di L1 juga ada di L2 dan, pada gilirannya, di L3. Hal ini memiliki konsekuensi yang sangat berguna untuk konsistensi: cukup dengan memperbarui cache level terendah dengan benar sudah cukup untuk mengontrol keadaan level lainnya tanpa harus terus-menerus mengakses RAM.

Mengapa caching bersama tingkat terakhir sangat penting untuk konsistensi?

Tanpa cache tingkat terakhir global ini, setiap inti prosesor harus memeriksa konsistensi secara langsung terhadap memori utama . Setiap kali baris memori dalam cache pribadi dimodifikasi, perlu diperiksa apakah inti prosesor lain menyimpan salinan baris yang sama dan, jika demikian, memperbarui atau membatalkannya di mana pun.

Dalam sistem dengan banyak inti prosesor, beban kerja pemeriksaan ini akan menghasilkan sejumlah besar transaksi ke RAM , sehingga meniadakan sebagian besar manfaat dari memiliki cache yang cepat. Dengan menempatkan cache bersama di antara inti prosesor dan memori, CPU dapat memusatkan kontrol koherensi di satu lokasi perantara.

Dalam banyak implementasi, cache pada level yang lebih tinggi (lebih jauh dari prosesor) berisi salinan baris yang ada di level yang lebih dekat ke inti . Dengan organisasi ini, protokol koherensi hanya perlu memastikan bahwa level terakhir disinkronkan dengan memori utama, dan bahwa level privat setiap inti disinkronkan dengan level yang tepat di atasnya.

Hal ini dapat divisualisasikan sebagai semacam boneka bersarang Rusia: cache tingkat ketiga mencakup isi dari tingkat kedua dan pertama , tingkat kedua mencakup isinya sendiri dan isi dari tingkat pertama, dan tingkat pertama hanya mengetahui baris-barisnya sendiri. Dengan demikian, dengan mengendalikan "boneka besar" (tingkat terakhir), sistem dapat mengkoordinasikan sisanya dengan lebih efisien.

Hasilnya adalah menjaga konsistensi menjadi lebih ekonomis dalam hal desain dan lalu lintas memori . Alih-alih memaksa setiap inti untuk terus-menerus berurusan dengan RAM, protokol ini beroperasi pada cache bersama dan dari sana mengelola baris mana yang harus diperbarui atau dibatalkan di cache pribadi.

Metode pembaruan: pembatalan dan pembaruan salinan

Masalah kritis muncul ketika dua atau lebih inti prosesor ingin mengakses, hampir secara bersamaan, baris data yang sama yang direplikasi di beberapa cache . Dalam konteks ini, sistem konsistensi biasanya menggunakan dua strategi mendasar saat menangani penulisan.

Metode pertama didasarkan pada invalidasi. Ketika sebuah kernel perlu menulis ke baris cache tertentu, protokol tersebut akan membatalkan semua salinan baris yang sama yang mungkin ada di cache lain . Hanya kernel yang akan menulis yang akan menyimpan baris tersebut dalam keadaan siap baca dan tulis; kernel lain, jika ingin menggunakan data tersebut lagi, harus memuat ulang baris tersebut dari level yang lebih tinggi (atau dari memori) dengan versi yang diperbarui.

Strategi kedua melibatkan pembaruan. Dalam hal ini, ketika kernel memodifikasi sebuah baris, sistem mencoba untuk secara otomatis menyebarkan konten baru ke salinan yang ada di cache lain . Dengan cara ini, semua cache yang menyimpan baris tersebut menerima versi yang diperbarui tanpa perlu membatalkan dan memuat ulang data tersebut di kemudian hari.

Setiap pendekatan memiliki kelebihan dan kekurangannya masing-masing. Invalidasi biasanya lebih efisien ketika penulisan sering terjadi karena menghindari kejenuhan sistem memori dengan pembaruan yang mungkin tidak segera dibutuhkan oleh inti prosesor lain. Sebaliknya, pembaruan dapat menguntungkan ketika banyak inti prosesor sering membaca data yang sama yang dimodifikasi relatif jarang , karena mengurangi latensi dengan tidak perlu memuat ulang baris setelah setiap invalidasi.

Dalam kedua kasus tersebut, kedua metode memanfaatkan status tambahan dan bit kontrol pada baris cache. Setiap baris biasanya mencakup informasi tentang apakah isinya cocok dengan yang ada di RAM , dan apakah baris tersebut dibagikan, dimodifikasi, eksklusif, dicadangkan, dll., tergantung pada protokol spesifik (MESI, MOESI, MSI, dll.). Hal ini memungkinkan perangkat keras untuk membuat keputusan cepat tentang apa yang harus dilakukan ketika operasi baca atau tulis terjadi pada baris yang sudah direplikasi.

  Xiaomi 17 Max: Performa Ekstrem dan Otonomi yang Belum Pernah Ada Sebelumnya

Memeriksa konsistensi antara cache dan memori.

Memverifikasi secara langsung konsistensi antara semua level cache CPU atau GPU dan memori utama akan menjadi tugas yang sangat besar, baik dari segi kompleksitas desain maupun biaya kinerja. Oleh karena itu, sistem modern mengatur verifikasi ini secara hierarkis.

Cache yang paling dekat dengan prosesor (L1, L2) biasanya tidak terhubung langsung ke RAM, tetapi ke tingkat cache berikutnya. Ini berarti bahwa konsistensi tidak divalidasi terhadap memori utama di setiap tingkat, melainkan terhadap tingkat yang lebih tinggi . Hal ini mengurangi jumlah akses RAM dan menyederhanakan logika yang dibutuhkan pada tingkat yang lebih rendah.

Pada akhirnya, perbandingan antara isi cache dan isi RAM dilakukan antara cache tingkat terakhir dan memori utama . Jika tingkat terakhir ini mempertahankan keadaan yang benar dan konsisten, dan setiap tingkat yang lebih rendah mempertahankan konsistensinya dengan tingkat di atasnya, seluruh hierarki tetap konsisten tanpa harus memeriksa setiap baris terhadap RAM berulang kali.

Ketika kernel menulis ke baris cache dan mengubah datanya, status baris tersebut ditandai untuk menunjukkan bahwa baris tersebut tidak lagi persis sama dengan salinan yang tersimpan di memori . Dari situ, protokol mengoordinasikan pembaruan: protokol menandai salinan yang sesuai di cache lain sebagai cadangan atau tidak valid dan, jika sesuai, menulis konten baru ke baris memori utama yang terkait.

Struktur bertingkat ini memungkinkan perubahan menyebar secara bertahap dari kernel, yang memperbarui data, ke memori utama, melewati setiap level cache dengan cara yang terkontrol. Dengan cara ini, menjaga konsistensi tidak menjadi hambatan yang tidak dapat diatasi bagi prosesor.

Koherensi perangkat keras versus koherensi perangkat lunak

Sejauh ini kita telah membahas mekanisme konsistensi yang sebagian besar diimplementasikan dalam perangkat keras: protokol, bit status, cache bersama, dll. Namun, ada pendekatan lain yang berupaya mengalihkan sebagian kompleksitas tersebut ke perangkat lunak , khususnya ke kompiler dan sistem operasi.

Skema konsistensi berbasis perangkat lunak berupaya mengurangi kebutuhan akan logika tambahan pada chip dengan menganalisis kode dan membuat keputusan pada saat kompilasi . Idenya adalah jika kompiler dapat menyimpulkan kapan dan bagaimana data bersama tertentu diakses, dalam banyak kasus, ia dapat mencegah data tersebut di-cache atau secara eksplisit mengelola visibilitasnya.

Pendekatan ini memiliki keunggulan yang jelas: sebagian beban kerja bergeser dari penyelesaian saat runtime ke penyelesaian saat kompilasi . Alih-alih perangkat keras mendeteksi dan menangani semua konflik secara langsung, kompiler mencoba mengantisipasinya dan menghasilkan kode yang menghindari situasi berbahaya.

Kelemahannya adalah analisis kode statis terbatas, dan oleh karena itu kompiler cenderung konservatif . Ini berarti bahwa, untuk menghindari pelanggaran konsistensi, mereka sering membuat keputusan yang mengurangi efektivitas cache. Jika mereka mencurigai bahwa beberapa data mungkin bermasalah, mereka sering mencegahnya untuk di-cache atau memaksa sinkronisasi lebih sering daripada yang benar-benar diperlukan.

Oleh karena itu, meskipun skema perangkat lunak ini menarik secara teori, terutama untuk menyederhanakan desain perangkat keras, dalam praktiknya skema ini tidak menggantikan dukungan koherensi yang terintegrasi ke dalam CPU itu sendiri , melainkan melengkapinya dalam beberapa skenario spesifik.

Peran kompiler dalam konsistensi cache

Salah satu elemen kunci dari pendekatan konsistensi berbasis perangkat lunak adalah peran kompiler. Kompiler dapat melakukan analisis mendalam terhadap kode dan menentukan struktur data bersama mana yang mungkin tidak aman untuk di-cache . Berdasarkan hal ini, kompiler menandai elemen-elemen tersebut dengan cara khusus atau menyesuaikan pembuatan kode.

Pendekatan paling sederhana, dan juga paling konservatif, adalah mencegah variabel data bersama agar tidak di-cache . Artinya, setiap akses ke variabel-variabel ini memaksa akses ke memori utama atau area yang tidak dapat di-cache. Ini menjamin konsistensi, tetapi melewatkan banyak peluang peningkatan kinerja, karena struktur bersama sebenarnya dapat digunakan secara pribadi selama periode tertentu, atau hanya dibaca pada periode lainnya.

  Superkomputer, AI, dan kembaran digital: panduan lengkap dalam bahasa Spanyol

Pada kenyataannya, masalah konsistensi hanya muncul selama interval ketika setidaknya satu proses dapat menulis ke variabel dan proses lain dapat membacanya . Di luar periode kritis ini, variabel dapat diperlakukan sebagai variabel yang hanya digunakan oleh satu thread atau bahkan sebagai konstanta efektif untuk sementara waktu, sehingga dapat di-cache tanpa masalah.

Strategi kompilasi paling canggih berupaya mengidentifikasi periode "aman" di mana variabel bersama dapat dianggap tidak menimbulkan konflik . Untuk melakukan ini, kompiler menganalisis jalur eksekusi, potensi akses bersamaan, dan pola sinkronisasi (kunci, bagian kritis, dll.). Berdasarkan analisis ini, kompiler membagi masa hidup variabel menjadi beberapa fase: beberapa cocok untuk caching, yang lain memerlukan penanganan khusus.

Selama periode kritis, ketika akses bersamaan dengan penulisan terdeteksi, kompiler menyisipkan instruksi tambahan ke dalam kode yang dihasilkan untuk menegakkan konsistensi cache . Instruksi ini dapat memaksa pembersihan cache, pemuatan ulang memori, penghalang memori, atau akses ke wilayah yang ditandai sebagai tidak dapat di-cache, tergantung pada model pemrograman dan arsitektur yang mendasarinya.

Hubungan antara kompiler, sistem operasi, dan perangkat keras

Frasa "kompilator menyisipkan instruksi ke dalam kode yang dihasilkan untuk menegakkan konsistensi cache" mungkin membuat orang berpikir bahwa sistem operasi membaca instruksi ini seolah-olah itu adalah petunjuk tingkat tinggi dan, berdasarkan itu, memutuskan bagaimana mengeksekusi program. Pada kenyataannya, mekanismenya agak berbeda.

Ketika kompiler menambahkan jenis instruksi ini, yang dimasukkannya ke dalam biner adalah operasi spesifik yang didukung oleh arsitektur atau lingkungan runtime . Misalnya, ia dapat menyisipkan instruksi pembersihan cache, penghalang memori, instruksi khusus untuk menandai wilayah sebagai tidak dapat di-cache, atau panggilan ke layanan sistem operasi yang mengkonfigurasi atribut memori.

Sistem operasi tidak menginterpretasikan instruksi-instruksi ini sebagai "komentar" atau "petunjuk" tingkat tinggi yang ditulis oleh kompiler; sistem operasi hanya mengeksekusi kode mesin seperti halnya instruksi lainnya . Namun, beberapa instruksi ini dirancang untuk berinteraksi dengan subsistem memori dan manajemen cache, sehingga mengubah cara CPU mengakses data tertentu.

Dengan kata lain, kompiler melakukan analisis pendahuluan dan menghasilkan kode yang, ketika dieksekusi, menghasilkan perilaku cache yang diinginkan . Sistem operasi berkolaborasi dengan menetapkan atribut memori (area yang dapat di-cache atau tidak dapat di-cache, kebijakan penulisan, dll.) dan menyediakan primitif sinkronisasi, tetapi sistem operasi tidak "membaca" instruksi khusus dalam arti menafsirkannya secara semantik seperti yang dilakukan kompiler.

Bisa juga terjadi bahwa perangkat keras, setelah melihat instruksi tertentu, mengaktifkan mekanisme koherensi atau sinkronisasi spesifik . Misalnya, instruksi fence atau barrier menjamin urutan akses memori dan memberlakukan efek visibilitas tertentu di seluruh hierarki cache. Dalam hal ini, terdapat kolaborasi tiga arah: kompiler memutuskan di mana menempatkan instruksi-instruksi ini, sistem operasi mengkonfigurasi lingkungan eksekusi, dan perangkat keras mengimplementasikan perilaku aktual pada tingkat cache dan bus memori.

Secara bersama-sama, semua elemen ini memastikan bahwa, bahkan dengan beberapa salinan data yang sama yang didistribusikan di berbagai cache dan memori utama, program paralel berjalan dengan model memori yang konsisten . Koherensi cache, jauh dari sekadar detail internal CPU, menjadi komponen sentral agar sistem multi-core dapat beroperasi dengan andal dan efisien.

Memahami bagaimana hierarki cache, protokol koherensi perangkat keras, dan teknik dukungan perangkat lunak berpadu akan memperjelas mengapa desain CPU modern memiliki struktur yang sangat mirip, dan mengapa kegagalan kecil pada salah satu mekanisme tersebut dapat memicu perilaku kacau dalam aplikasi konkuren yang sepenuhnya bergantung pada semua inti prosesor untuk melihat data yang sama pada waktu yang tepat.