Jika Anda pernah melihat LLM menghasilkan respons panjang dan bertanya-tanya mengapa kecepatannya melambat setelah kilatan prompt awal, Anda sedang menyaksikan hambatan perangkat keras (hardware bottleneck) secara langsung. Kebanyakan pengembang menyalahkan kode Python mereka, framework, atau ukuran model yang sangat besar. Mereka melakukan profiling pada fungsi, mengganti optimizer, dan memangkas milidetik pada preprocessing. Tidak ada satu pun dari hal itu yang memperbaiki masalah sebenarnya. Batas kecepatannya bukan pada perangkat lunak Anda. Batasnya ada pada silikon.
Setiap pekerjaan inferensi model bahasa besar bergantung pada dua sifat fisik GPU yang ada di server Anda: seberapa cepat ia dapat mengolah angka, dan seberapa cepat ia dapat memindahkan angka-angka tersebut ke posisi untuk diolah.
Matematika Itu Murah. Memindahkan Data Tidak
Pemasaran GPU senang berbicara tentang komputasi (compute). Triliunan operasi titik mengambang (floating-point operations) per detik. Angkanya sangat mencengangkan. Namun, komputasi hanyalah setengah dari ceritanya. Setengah lainnya adalah bandwidth memori, yaitu laju data berpindah dari memori bandwidth tinggi ke inti komputasi (compute cores) tempat aritmetika sebenarnya terjadi.
Sebuah LLM tidak dapat berjalan lebih cepat daripada tautan yang paling lemah di antara keduanya. Bayangkan sebuah dapur komersial dengan dua puluh koki ahli. Ovennya panas, pisaunya tajam, dan setiap juru masak sudah siap. Namun, pengiriman bahan makanan datang menggunakan sepeda, satu keranjang demi satu keranjang. Dapur pun terhenti. Menambah lebih banyak koki tidak akan memperbaikinya. Membeli oven yang lebih cepat pun tidak akan memperbaikinya. Hambatannya ada pada jalanan.
Pada GPU pusat data modern, unit aritmetika sangat kuat sehingga mereka sering kali menyelesaikan kalkulasi mereka lalu duduk menganggur, membuang siklus saat menunggu bobot (weights) dan aktivasi mengalir melalui memori. Ketidakseimbangan ini bukanlah bug dalam kode Anda. Ini adalah realitas fisik dari bagaimana chip dibuat. Bandwidth memori tidak mampu mengimbangi komputasi mentah, dan LLM sangat terdampak oleh ketidakseimbangan ini karena proses forward pass mereka memerlukan akses ke setiap parameter untuk setiap token output.
Mengapa Prompt Terasa Cepat dan Generasi Terasa Lambat
Inferensi LLM terbagi menjadi dua fase yang berbeda, dan keduanya memberikan beban pada perangkat keras dengan cara yang sangat berbeda.
Prefill terjadi saat prompt Anda pertama kali masuk ke model. Semua token tiba secara bersamaan. GPU dapat memprosesnya secara paralel menggunakan perkalian matriks-matriks besar. Ribuan unit aritmetika bekerja sekaligus, dan beban kerjanya tetap padat. Fase ini bersifat compute-bound. Lonjakan kecepatan tiba-tiba yang Anda lihat di awal? Itulah GPU yang melakukan tepat seperti apa yang seharusnya ia lakukan.
Decode adalah saat segalanya menjadi sulit. Ketika model menghasilkan token berikutnya, ia melakukannya satu per satu. Tahap ini bergantung pada operasi matriks-vektor, yang hanya menggunakan sebagian kecil dari kapasitas paralel GPU. Lebih buruk lagi, setiap token baru memaksa GPU untuk memuat ulang seluruh bobot model dari memori. Unit aritmetika ingin bekerja. Sebaliknya, mereka menunggu. Decode bersifat memory-bound. GPU secara efektif bertindak sebagai pengatur lalu lintas yang mahal, mengangkut parameter bolak-balik melalui bus memori sementara mesin matematika mendingin. Inilah sebabnya mengapa respons seratus kata dapat memakan waktu sepuluh detik meskipun analisis prompt awal terasa instan.
KV cache membuat hal ini menjadi lebih menarik. Selama decode, model menyimpan tensor key dan value untuk setiap token sebelumnya agar tidak perlu menghitung ulang attention dari awal. Cache tersebut tumbuh seiring dengan panjang urutan (sequence length). Ia juga berada di dalam memori. Jadi sekarang GPU tidak hanya memuat ulang bobot; ia membaca dan menulis cache yang terus berkembang pada setiap forward pass. Inti komputasi hampir tidak bekerja keras, sementara bus memori bekerja keras untuk keduanya.
Melawan Memory Wall
Para insinyur telah mengembangkan sejumlah teknik untuk mengurangi seberapa banyak data yang harus dipindahkan, atau setidaknya untuk berbagi biaya pemindahannya.
Batching adalah yang paling sederhana. Jika permintaan satu pengguna memaksa pemuatan bobot penuh dari memori, maka memproses delapan atau enam belas permintaan sekaligus memungkinkan GPU untuk membagi beban tersebut ke semua permintaan. Bobot dibaca sekali dan digunakan kembali untuk setiap urutan dalam batch tersebut. Dalam produksi, sistem penjadwalan yang canggih mengelompokkan permintaan secara dinamis, terkadang disebut continuous atau in-flight batching, sehingga GPU jarang berhenti. Ini adalah perbedaan antara sebuah bus dan enam belas mobil terpisah di rute yang sama.
Quantization mengatasi masalah bandwidth secara langsung. Bobot model biasanya disimpan dalam format floating-point enam belas bit. Dengan mengompresinya menjadi integer delapan bit atau bahkan empat bit, Anda secara harfiah memotong jumlah data yang mengalir melalui bus hingga setengahnya atau lebih. Model tersebut tetap membutuhkan presisi yang cukup untuk menghasilkan output yang koheren, tetapi metode kuantisasi pasca-pelatihan modern dapat memperkecil jejak memori model secara drastis tanpa merusak kualitas. Lebih sedikit data yang mengalir berarti lebih sedikit waktu yang dihabiskan untuk menunggu di pengontrol memori.
FlashAttention menyusun ulang mekanisme atensi agar hasil antara tetap berada di dalam memori on-chip GPU yang cepat. Atensi standar harus menulis matriks atensi yang besar ke memori eksternal yang lambat dan kemudian membacanya kembali. FlashAttention memecah perhitungan menjadi ubin (tiles) yang lebih kecil agar muat di SRAM, melakukan langkah softmax dan penskalaan secara on-chip, dan hanya menulis output akhir kembali ke memori bandwidth tinggi. Teknik ini menukar sedikit tambahan komputasi untuk mengurangi perjalanan bolak-balik ke memori utama, yang hampir selalu menjadi pilihan yang menguntungkan.
PagedAttention menyelesaikan jenis pemborosan memori yang berbeda. Selama proses dekode, KV cache tumbuh secara tidak terduga. Sistem tradisional mengalokasikan blok memori yang tetap dan kontinu untuk setiap urutan, menyisakan celah besar saat beberapa urutan berakhir lebih awal dan yang lainnya berkembang. PagedAttention meminjam konsep memori virtual dari sistem operasi. Ia menyimpan entri KV cache dalam blok berukuran tetap yang dapat dialokasikan secara non-kontinu dan dipetakan melalui tabel indireksi. Hal ini menghentikan memori agar tidak menganggur di dalam buffer yang dipesan tetapi setengah kosong, dan memungkinkan ukuran batch yang lebih besar, yang pada gilirannya meningkatkan throughput secara keseluruhan dengan menjaga bus memori tetap sibuk dengan pekerjaan yang berguna alih-alih overhead fragmentasi.
Ubah Pertanyaannya
Ketika latensi melonjak, terlalu banyak tim bertanya apakah mereka harus beralih ke model yang lebih kecil atau menulis ulang server inferensi mereka. Pertanyaan-pertanyaan tersebut penting, tetapi itu adalah hal sekunder. Pertanyaan pertama seharusnya adalah tentang perangkat keras itu sendiri. Apakah GPU Anda benar-benar sibuk melakukan komputasi, atau ia kekurangan data?
Lihat metrik utilisasi Anda. Profil saturasi bandwidth memori bersamaan dengan okupansi komputasi GPU. Jika Anda melihat kontensi memori yang tinggi dan intensitas aritmatika yang rendah selama dekode, Anda tidak memiliki masalah arsitektur model. Anda memiliki masalah fisika. Solusinya tidak akan datang dari kode Python yang lebih bersih. Solusinya akan datang dari batching yang lebih agresif, menguantisasi bobot Anda agar dapat melewati jalur (pipe) lebih cepat, menyusun ulang atensi agar tetap berada di on-chip, dan mengelola KV cache sehingga Anda dapat memasukkan batch yang lebih besar tanpa kehabisan ruang.
Begitu Anda melihat inferensi melalui lensa ini, optimasi menjadi mekanis. Anda berhenti mengejar mitos tentang kecerdasan model yang memperlambat segalanya dan mulai membuat keputusan teknik yang didasarkan pada apa yang sebenarnya dapat diberikan oleh perangkat keras. Itulah pergeseran yang membedakan sistem produksi yang dapat diskalakan dari sistem yang hanya sekadar berfungsi.
