NUMA Membuat Lokasi Memori Menjadi Bagian dari Biaya Akses

Server multiprosesor berukuran besar dapat menyediakan satu ruang alamat fisik, tetapi setiap prosesor belum tentu memiliki jalur yang sama menuju memori tersebut. Akses ke halaman memori yang terhubung dekat dengan prosesor tempat sebuah thread berjalan dapat menempuh jalur yang lebih pendek dibanding akses ke memori yang terhubung ke paket prosesor atau node NUMA lain.

Susunan ini disebut non-uniform memory access atau NUMA. Pendekatan tersebut memungkinkan kapasitas dan bandwidth memori bertambah melalui beberapa soket prosesor atau kelompok chiplet tanpa memaksa seluruh permintaan memori melewati satu pengendali terpusat.

Dampaknya cukup jelas: lokasi fisik menjadi bagian dari performa memori. Dua pointer dapat sama-sama menunjuk ke RAM yang valid, tetapi biaya aksesnya bisa berbeda untuk CPU yang sama.

Memori lokal dan remote melewati jalur yang berbeda

Sebuah node NUMA biasanya mengelompokkan beberapa core prosesor dengan satu atau lebih memory controller serta sebagian RAM sistem. Akses ke memori yang terkait dengan node tersebut disebut akses lokal. Akses ke memori milik node lain disebut akses remote dan harus melewati interkoneksi antarpemroses.

Jalur remote dapat menambah latensi sekaligus memakai bandwidth interkoneksi. Besarnya penalti bergantung pada platform, topologi, generasi memori, beban prosesor, dan lalu lintas dari node lain.

Memori remote bukanlah jenis RAM yang secara intrinsik lebih lambat. Perbedaannya muncul dari jalur antara core yang meminta data dan memory controller yang melayani alamat tujuan. Sebuah halaman yang remote untuk satu node bisa menjadi lokal untuk node lain.

Sifat yang bergantung arah ini membedakan NUMA dari hierarki sederhana seperti L1, L2, L3, dan DRAM. Level cache menjelaskan tempat sebuah salinan data berada saat ini. Lokalitas NUMA menjelaskan memory controller mana yang memiliki halaman fisik dan jalur apa yang harus ditempuh peminta untuk mencapainya.

Satu ruang alamat tidak berarti satu biaya akses

Sistem operasi biasanya memberikan ruang alamat virtual kepada proses biasa. Halaman virtual dipetakan ke halaman fisik, dan halaman fisik tersebut dapat berada pada node NUMA yang berbeda.

Karena itu, aplikasi dapat mengalokasikan buffer besar tanpa harus menyimpan nomor node pada setiap pointer. Sistem operasi dan kebijakan runtime menentukan lokasi halaman fisik pendukung, kecuali aplikasi meminta kebijakan tertentu secara eksplisit.

Abstraksi ini mempertahankan semantik pointer yang normal, tetapi tidak menghapus topologi perangkat keras.

Sebuah thread dapat berpindah dari satu CPU ke CPU lain setelah halaman memorinya sudah ditempatkan. Alamat virtualnya tetap valid, tetapi akses yang sebelumnya lokal dapat berubah menjadi remote. Sebaliknya, memindahkan data tanpa memindahkan thread yang menggunakannya juga dapat membalik pola lokalitas.

Dengan demikian, performa NUMA ditentukan oleh hubungan antara penempatan komputasi dan penempatan data, bukan oleh salah satunya saja.

First-touch mengaitkan proses inisialisasi dengan lokasi halaman

Banyak kebijakan NUMA pada sistem operasi menggunakan strategi first-touch untuk memori anonim. Memesan rentang alamat virtual tidak selalu langsung menetapkan seluruh halaman fisiknya. Halaman fisik biasanya baru dialokasikan ketika kode pertama kali menulis atau memicu page fault pada halaman tersebut, dan penempatannya dapat mengikuti node tempat thread pemicu berjalan.

Karena itu, pola inisialisasi paralel menjadi penting.

Bayangkan satu thread mengalokasikan array besar lalu menginisialisasi seluruh halaman saat berjalan di node 0. Setelah itu, beberapa worker membagi array tersebut di antara core pada node 0 dan node 1. Worker di node 1 dapat menghasilkan banyak akses remote karena proses inisialisasi sebelumnya memusatkan halaman pada node 0.

Jika setiap worker menginisialisasi bagian data yang nantinya akan diproses sambil dipasang pada node yang sesuai, first-touch dapat menyebarkan halaman lebih dekat ke pihak yang akan menggunakannya.

Kebijakan persisnya bergantung pada sistem operasi. First-touch merupakan perilaku yang umum, bukan aturan universal untuk setiap jenis alokasi.

CPU affinity dapat membuat lokalitas lebih stabil

Scheduler memindahkan thread yang siap berjalan di antara CPU untuk menyeimbangkan beban dan memenuhi kebijakan penjadwalan. Migrasi sering bermanfaat, tetapi perpindahan yang terlalu sering dapat mengganggu penempatan NUMA yang sudah dirancang dengan sengaja.

CPU affinity membatasi tempat sebuah thread atau proses boleh berjalan. Jika dipadukan dengan kebijakan memori yang selaras, affinity dapat menjaga workload tetap dekat dengan halaman yang paling sering diakses.

Pinning tidak otomatis membuat program lebih cepat. Affinity yang terlalu ketat dapat membuat core menganggur, meningkatkan kontensi, atau menghambat scheduler saat beban berubah. Teknik ini paling berguna ketika workload memiliki kepemilikan yang stabil terhadap area memori besar atau ketika pengukuran menunjukkan lalu lintas remote yang signifikan.

Tujuannya bukan menghilangkan migrasi dengan segala cara, melainkan menjaga hubungan utama antara komputasi dan data tetap efisien.

Interleaving menukar lokalitas dengan keseimbangan kapasitas dan bandwidth

Kebijakan memori NUMA juga dapat menyebarkan halaman ke beberapa node, bukan menempatkannya terutama di dekat satu thread. Interleaving berguna untuk workload yang thread-thread-nya mengakses satu area bersama secara relatif merata dari beberapa node.

Kebijakan ini mengorbankan sebagian akses lokal karena setiap node akan menemui halaman yang dimiliki node lain. Sebagai gantinya, beban pada memory controller dapat tersebar sehingga satu node tidak menjadi titik panas kapasitas atau bandwidth.

Kebijakan terbaik bergantung pada pola akses. Workload yang terbagi jelas dengan kepemilikan data per thread biasanya diuntungkan oleh penempatan lokal. Sebaliknya, workload streaming yang banyak berbagi data dapat memperoleh manfaat dari penyebaran halaman ke beberapa memory controller.

Aturan sederhana seperti “selalu simpan memori secara lokal” mengabaikan kenyataan bahwa keseimbangan bandwidth kadang sama pentingnya dengan latensi.

Cache mengurangi lalu lintas tetapi tidak menghapus efek NUMA

Cache prosesor dapat melayani akses berulang tanpa kembali ke DRAM, sehingga cache hit dapat menyamarkan lokasi halaman fisik di belakangnya untuk akses tersebut.

NUMA tetap penting ketika cache line harus diambil, dikeluarkan, atau dipertukarkan antarpemroses. Working set besar, pemindaian streaming, buffer database, array ilmiah, dan analitik in-memory dapat menghasilkan lalu lintas memori yang cukup tinggi hingga pengaruh topologi terlihat pada throughput maupun tail latency.

Data bersama yang dapat ditulis menambah biaya lain. Cache line yang dimodifikasi oleh core pada node berbeda dapat berpindah kepemilikan melalui interkoneksi meskipun halaman fisiknya sendiri tidak bergerak. Ini adalah efek koherensi yang berada di atas persoalan penempatan NUMA.

Menempatkan halaman dekat dengan sebuah thread tidak akan memperbaiki desain yang terus-menerus memindahkan kepemilikan cache line yang sama di antara core yang berjauhan.

Tekanan kapasitas dapat memaksa alokasi remote

Penempatan lokal dibatasi oleh memori yang tersedia. Jika satu node tidak memiliki cukup halaman kosong, sistem operasi dapat menempatkan halaman baru di node lain, tergantung kebijakan dan konfigurasi platform.

Sebuah proses dapat memulai dengan lokalitas yang baik lalu secara bertahap mengumpulkan halaman remote ketika tekanan memori berubah. Layanan yang berjalan lama lebih rentan karena penempatan thread, pola alokasi, dan kapasitas kosong ikut berubah seiring waktu.

Kebijakan node binding yang ketat dapat menolak alokasi alih-alih melakukan fallback ke node lain. Perilaku ini dapat tepat untuk workload khusus, tetapi menciptakan mode kegagalan berbeda: RAM masih tersedia di bagian lain mesin, sementara node yang diminta tidak mampu memenuhi alokasi.

Tuning NUMA karena itu harus mempertimbangkan kapasitas sekaligus kecepatan.

Pengukuran harus memisahkan masalah lokalitas dari tekanan memori secara umum

Workload yang lambat dan berat di memori belum tentu memiliki masalah NUMA. Cache miss, bandwidth memori yang tidak mencukupi, page fault, swapping, false sharing, lock contention, dan tata letak data yang buruk dapat menghasilkan gejala serupa.

Diagnosis yang berguna menggabungkan informasi topologi dengan counter atau statistik sistem operasi yang membedakan alokasi maupun lalu lintas lokal dan remote. Membandingkan beberapa run dengan CPU affinity dan penempatan memori yang dikendalikan dapat menunjukkan apakah topologi benar-benar memberi dampak berarti.

Benchmark juga perlu berlangsung cukup lama dan memakai working set yang cukup besar agar mewakili aplikasi sebenarnya. Uji kecil yang seluruh datanya muat di cache mungkin hampir tidak menunjukkan penalti NUMA, meskipun workload produksi memindai ratusan gigabyte data.

NUMA menambahkan satu dimensi lagi pada performa memori: tempat kode berjalan relatif terhadap lokasi halaman fisiknya. Penempatan yang baik menjaga data yang sering dipakai tetap dekat ketika latensi menjadi faktor utama, menyebarkan lalu lintas ketika bandwidth lebih penting, dan menghindari anggapan bahwa satu ruang alamat berarti satu mesin fisik yang seragam.