False Sharing pada Cache Line Memindahkan Ownership Koherensi Antar-CPU
Dua thread dapat memperbarui variabel berbeda tanpa berbagi lock atau menyentuh byte yang sama, tetapi tetap saling mengganggu pada level hardware. Jika kedua variabel berada dalam cache line yang sama, sistem multiprosesor koheren memperlakukan penyimpanannya sebagai satu unit koherensi. Write berulang dari CPU berbeda karena itu dapat memindahkan ownership line tersebut antar-cache meskipun program menganggap variabelnya independen.
Efek ini disebut false sharing. Dampaknya muncul dari kombinasi layout memori, pola akses, dan granularitas koherensi; kedekatan field dalam sebuah struktur saja belum membuktikan adanya masalah performa.
Koherensi bekerja di bawah batas objek bahasa pemrograman
Source code memberi identitas tersendiri pada setiap field, tetapi cache coherence umumnya melacak line berukuran tetap, bukan field C, value Rust, counter, atau elemen array. Sebuah write mengharuskan CPU yang mengeksekusinya memperoleh state koherensi yang mengizinkan modifikasi line. Copy yang tersimpan pada CPU lain harus bertransisi sesuai aturan protokol koherensi.
Pertimbangkan dua counter yang berada dalam satu line:
cache line
+----------------------+----------------------+
| counter_a | counter_b |
| ditulis CPU 0 | ditulis CPU 1 |
+----------------------+----------------------+Kedua CPU tidak berebut counter yang sama. Keduanya berebut izin untuk memodifikasi unit koherensi yang sama. Write ke counter_a dapat memengaruhi state cache yang juga memuat counter_b, lalu write berikutnya ke counter_b dapat memerlukan perpindahan ownership lagi.
State protokol dan jalur transfer persisnya bergantung pada arsitektur dan implementasi. Nama state keluarga MESI berguna sebagai model, tetapi software tidak dapat menyimpulkan urutan transfer fisik tertentu hanya dari label tersebut.
Cache line yang dibagi tidak selalu merugikan
Read-only sharing merupakan perilaku cache yang normal dan berguna. Beberapa CPU dapat menyimpan copy line yang berisi data immutable atau dominan read tanpa perpindahan ownership berulang seperti pada write yang saling bersaing.
False sharing menjadi relevan ketika akses concurrent mencakup write dan line tersebut cukup aktif sehingga traffic koherensi berdampak. Pola yang umum mencakup counter per-thread yang berdekatan dalam array, field yang sering dimodifikasi di samping data yang dibaca CPU lain, atau variabel global yang tidak berkaitan tetapi berada pada line yang sama.
Layout yang tidak bermasalah pada satu workload dapat menjadi mahal pada workload lain. Penempatan thread, frekuensi write, topologi CPU, alignment objek, dan implementasi hierarki cache ikut menentukan biaya yang terlihat. Tidak ada penalti latensi portabel yang dapat diberikan untuk setiap kejadian false sharing.
Padding mengubah biaya koherensi sekaligus memori
Memisahkan field yang sering ditulis ke cache line berbeda dapat menghilangkan relasi koherensi yang tidak disengaja:
line 0
+----------------------+
| counter_a |
+----------------------+
line 1
+----------------------+
| counter_b |
+----------------------+Layout tersebut tetap memiliki biaya. Padding memperbesar objek, memakai lebih banyak kapasitas cache, dapat meningkatkan footprint memori, dan dapat menambah tekanan pada cakupan TLB jika diterapkan pada koleksi besar. Perubahan itu juga dapat memindahkan field lain ke kombinasi baru yang menghasilkan pola sharing berbeda.
Karena itu, alignment cache line merupakan keputusan layout yang terarah, bukan aturan universal untuk data concurrent. Field yang ditulis bersama oleh CPU yang sama dapat memperoleh manfaat dari posisi berdekatan, sedangkan writer independen yang sama-sama aktif lebih layak dipisahkan.
State per-CPU mengurangi traffic ownership dengan mengubah model data
Pendekatan lain adalah berhenti memperbarui satu lokasi shared pada setiap operasi. Counter per-CPU dan agregasi berbasis batch memberi setiap CPU jalur update lokal, kemudian menggabungkan nilainya pada batas yang lebih jarang.
Perubahan ini lebih luas daripada layout. Counter global yang diperbarui langsung dapat menawarkan semantik visibility tertentu, sedangkan agregasi per-CPU dapat mengekspos nilai yang disusun dari beberapa state lokal. Desain yang tepat bergantung pada kontrak konsistensi yang diperlukan pemanggil.
Linux banyak memakai data per-CPU pada jalur yang menganggap pengurangan shared write sepadan dengan semantik agregasi tambahan. Teknik ini menekan beban koherensi dengan mengurangi write lintas-CPU, bukan sekadar memberi jarak lebih lebar pada pola write yang sama.
Pengukuran perlu menemukan line yang mengalami contention
Peningkatan utilisasi CPU atau benchmark multithread yang melambat tidak dengan sendirinya menunjukkan false sharing. Lock contention, bandwidth memori, perpindahan scheduler, penempatan NUMA, perilaku branch, dan efek cache lain dapat menghasilkan gejala serupa.
Pada Linux, perf c2c dapat melaporkan aktivitas cache-to-cache dan mengaitkan line yang aktif dengan lokasi akses pada hardware yang didukung. Tool layout struktur seperti pahole kemudian dapat menghubungkan offset dengan field yang menempati line yang sama. Ketersediaan dan interpretasi hardware event berbeda antarprosesor, sehingga event yang dilaporkan tetap merupakan bukti spesifik platform, bukan interface pengukuran universal.
Unit analisis yang berguna adalah cache line beserta code path yang mengaksesnya. Setelah writer dan reader teridentifikasi, perubahan layout dapat diukur dengan workload yang sama. Penurunan event koherensi yang disertai perbaikan workload memberikan bukti lebih kuat dibandingkan perubahan alignment yang hanya didasarkan pada inspeksi source code.
Layout merupakan bagian dari performa concurrency
False sharing berada pada batas antara independensi software dan granularitas hardware. Variabel yang berbeda dapat tidak berkaitan secara logis tetapi tetap terikat secara fisik oleh unit koherensi yang memuatnya.
Batas praktisnya spesifik: data yang sering diakses dengan write lintas-CPU layak diperiksa pada level cache line ketika skalabilitas menurun. Pemisahan field, state per-CPU, atau pengurangan frekuensi write dapat mengubah pola koherensi, tetapi masing-masing juga mengubah penggunaan memori, layout, atau semantik visibility. Perbaikan yang tepat mengikuti pola akses yang terukur, bukan sekadar kedekatan field.