Latensi lebih rendah dan throughput lebih tinggi dengan penerapan DeepSeek multi-node

Penerapan multi-GPU meningkatkan performa model MoE pada aspek kecepatan dan skala secara bersamaan

PenulisPerplexity Research

Dalam kebanyakan sistem, latensi dan throughput sering kali merupakan tujuan yang saling bertentangan yang memerlukan kompromi selama desain dan penerapan. Misalnya, dalam model bahasa besar yang padat, meningkatkan ukuran batch dapat meningkatkan throughput tetapi juga meningkatkan latensi; meningkatkan paralelisme tensor dalam satu mesin dapat mengurangi latensi tetapi menurunkan jumlah replika, yang menyebabkan throughput lebih rendah.

Model Mixture of Experts (MoE) seperti DeepSeek-V3/R1 baru-baru ini menunjukkan kemampuan model dan efisiensi operasional yang sangat baik. Sebagai contoh, model DeepSeek-V3/R1 memiliki total 671B parameter, tetapi setiap token hanya menggunakan 37B parameter selama inferensi. Arsitektur model ini menghadirkan tantangan sekaligus peluang bagi sistem inferensi.

Artikel ini menunjukkan bahwa, bertentangan dengan sistem konvensional, model MoE seperti DeepSeek-V3/R1 dapat secara bersamaan mencapai throughput yang lebih tinggi dan latensi yang lebih rendah saat menggunakan lebih banyak GPU dalam penerapan multi-node di sebagian besar skenario.

Arsitektur Penerapan

Penerapan satu node di seluruh NVLink, dengan perhatian dan komputasi pakar didistribusikan di seluruh GPU.
Penerapan multi-node di seluruh InfiniBand, dengan grup GPU terhubung di dalam dan antar node.

Karena banyaknya pakar kecil yang dimiliki model ini, penerapan harus disebar ke beberapa perangkat. Kami mempertimbangkan penerapan node tunggal pada satu node dengan 8 GPU H200 dan penerapan multi-node pada 8 GPU H100.

Kedua arsitektur penerapan memanfaatkan Paralelisme Data, yang diatur melalui penjadwal permintaan buatan kami sendiri. Implementasi paralelisme data melibatkan peluncuran beberapa instance mesin inferensi, yang masing-masing beroperasi secara independen untuk melayani dan mempertahankan permintaan. Penjadwal permintaan, yang berinteraksi dengan mesin melalui GRPC, bertanggung jawab untuk menyebarkan permintaan secara merata, sekaligus memfasilitasi penggunaan kembali KV, mengirimkan permintaan dengan prefiks yang cocok sebagian ke server yang berisi cache. Instance mesin tidak mencakup beberapa node. Instance tersebut secara opsional dapat menggunakan paralelisme tensor untuk melakukan shard pada atensi di beberapa perangkat. Instance saling terhubung melalui NVLink dalam kasus node tunggal atau InfiniBand untuk kasus multi-node, yang mengirimkan dan mengumpulkan pakar.

Konfigurasi penerapan node tunggal memberikan latensi superior dengan ukuran batch kecil; namun, performa menurun dengan cepat di bawah kondisi beban yang meningkat.

Untuk menerapkan mesin penyajian, kami meluncurkan satu pod per node yang menghosting beberapa instance mesin. PyTorch bertanggung jawab untuk menyiapkan komunikasi terdistribusi dan menegosiasikan inisialisasi NVSHMEM. Untuk komunikasi, kami mengandalkan kernel CUDA kustom yang dijelaskan dalam postingan blog sebelumnya. Implementasi kedua penerapan tersebut hampir identik, dengan model yang memilih kernel yang benar untuk digunakan berdasarkan fabrik yang menerapkan paralelisme pakar.

Teknik paralelisasi

Sebelum menyelami perbandingan performa kami, penting untuk memahami strategi paralelisasi utama yang memungkinkan penerapan model MoE masif seperti DeepSeek-V3/R1.

Paralelisasi Tensor

Dalam inferensi LLM, Paralelisasi Tensor (TP) biasanya digunakan untuk mengurangi penggunaan memori dan komputasi per GPU, sehingga mengurangi latensi. Biasanya, kita dapat melakukan shard pada Proyeksi Linear di Lapisan Atensi dan MLP di sepanjang dimensi baris atau kolom, dan melakukan shard pada operasi Atensi di sepanjang dimensi kepala atensi.

Dengan TP, arsitektur Llama-3 tidak memiliki komputasi duplikat untuk operasi Proyeksi Linear dan Atensi di seluruh GPU, yang merupakan metode sharding yang ideal. Namun, dalam model DeepSeek-V3/R1, TP tidak dapat mencapai hal ini.

Model DeepSeek-V3/R1 menggunakan Multi-Latent Attention (MLA). Lapisan MLA pertama-tama menggunakan Proyeksi Linear kv_a_proj untuk menghitung vektor laten, lalu menggunakan Proyeksi Linear kv_b_proj lainnya untuk mengubahnya ke dalam ruang setiap kepala atensi. Karena semua kepala atensi membagikan vektor laten yang sama, TP tidak dapat melakukan shard pada vektor laten, sehingga semua Peringkat TP perlu mereplikasi parameter dan komputasi kv_a_proj dan kv_b_proj. Demikian pula, karena MLA menyimpan vektor laten di Cache KV, setiap Peringkat TP menyimpan salinan Cache KV yang identik.

Terlepas dari beberapa duplikasi dalam MLA, Paralelisasi Tensor tetap memberikan pengurangan parsial dalam permintaan komputasi, menjadikannya berharga untuk skenario yang memerlukan kecepatan output tinggi.

Paralelisasi Pakar

Model DeepSeek-V3/R1 menggantikan Lapisan MLP dengan Lapisan MoE. Lapisan MoE memiliki 256 pakar terarah dan satu pakar bersama. Setiap token dikirimkan ke 8 pakar terarah yang berbeda untuk komputasi, dan hasilnya dijumlahkan secara berbobot. Setiap token juga melakukan komputasi pada pakar bersama, dan hasilnya ditambahkan ke hasil dari pakar terarah.

Paralelisasi Pakar (EP) berfungsi sebagai pendekatan sharding tipikal untuk Lapisan MoE, dengan setiap GPU mengelola 256 / EP pakar terarah sambil mempertahankan salinan pakar bersama. Dibandingkan dengan TP, keunggulan EP adalah dapat mendistribusikan komputasi ke lebih banyak GPU, sehingga mengurangi komputasi dan penggunaan memori per GPU.

Sebelum melakukan komputasi pakar, semua GPU perlu melakukan komunikasi AllToAll untuk mengirimkan token ke GPU tempat pakar terkait berada; setelah komputasi pakar, komunikasi AllToAll lainnya diperlukan untuk mengumpulkan hasil komputasi dari berbagai GPU dan melakukan penjumlahan berbobot. Kami menerapkan versi dioptimalkan dari kedua Kernel komunikasi AllToAll ini, Dispatch dan Combine, menggunakan NVSHMEM. Dalam postingan blog kami sebelumnya, kami merinci implementasinya, dan kernel kami telah di-open-source-kan di GitHub.

Paralelisasi Data

Dengan EP, kita dapat mendistribusikan komputasi MoE ke 128 atau bahkan lebih banyak GPU. Namun, komputasi MLA tidak dapat dipartisi dengan EP. Pada titik ini, kita dapat memperkenalkan Paralelisasi Data (DP). Setiap Grup DP memiliki salinan Lapisan MLA yang lengkap. Setiap Grup DP menerima input yang berbeda dan melakukan komputasi Lapisan MLA secara independen.

DP dan TP lapisan MLA dapat digabungkan, dengan satu Grup DP dibagi menjadi beberapa Peringkat TP. EP lapisan MoE dapat digabungkan dengan DP/TP Lapisan MLA. EP = DP * TP. Misalnya, pada 16 mesin, EP128 DP32 TP4 berarti mendistribusikan pakar terarah ke 128 GPU, dengan setiap 4 GPU membentuk Grup DP, dengan total 32 Grup DP independen.

Node Tunggal vs Multi-Node

Parameter 671B DeepSeek melebihi kapasitas memori dari satu mesin H100 8-GPU (80 GB * 8), tetapi satu mesin H200 8-GPU dapat sepenuhnya menampung seluruh model (141 GB * 8). Menggunakan konfigurasi EP8 DP8 TP1, model menggunakan sekitar 100 GB memori per GPU, menyisakan sekitar 40 GB untuk Cache KV dan hasil antara lainnya. Satu token menduduki 70.272 byte Cache KV. Dengan asumsi setiap permintaan memiliki 5.000 token, setiap GPU dapat menampung sekitar 100 permintaan.

Kami ingin memahami perbedaan performa antara penerapan node tunggal dan multi-node di bawah berbagai konfigurasi. Kami menggunakan satu mesin H200 untuk penerapan node tunggal dan hingga 16 mesin H100 untuk penerapan multi-node. Untuk setiap lingkungan penerapan, kami menggunakan kombinasi TP 1, 2, 4, 8, dan ukuran batch per GPU 1, 2, 4, 8, 16, 32, 64, 128. Kami berasumsi setiap permintaan memiliki panjang Cache KV 5.000 token. Kami juga berasumsi Multi-Token Prediction (MTP) memprediksi 1 token tambahan (yaitu, panjang kueri setiap permintaan adalah 2), dan secara konservatif berasumsi tingkat penerimaan 60%. Gambar di bawah menunjukkan throughput dan kecepatan output untuk berbagai konfigurasi.

Frontier Pareto latensi–throughput untuk berbagai konfigurasi paralel pakar.

Sumbu horizontal mewakili kecepatan output per permintaan dalam token/s. Sumbu vertical menggunakan skala logaritmik untuk menunjukkan throughput per mesin dalam token/s. Kami menandai Pareto Frontier untuk setiap konfigurasi EP dengan garis berwarna berbeda.

Dalam skenario dengan kebutuhan kecepatan output yang sangat tinggi, menggunakan EP8 DP1 TP8 node tunggal dengan ukuran batch 1 dapat mencapai kecepatan output melebihi 100 token/s, tetapi throughput-nya sangat rendah, setara dengan kecepatan output. Dalam skenario ini, seluruh batch hanya memiliki 2 token, yang dapat dikirimkan ke paling banyak 2*8=16 pakar, mengaktifkan total paling banyak 57B parameter.

Dalam rentang kecepatan output 80-40 token/s, saat throughput meningkat, kecepatan output menurun secara signifikan. Sebaliknya, EP128 memiliki throughput sekitar 5x lebih tinggi daripada penerapan node tunggal pada kecepatan output yang sama.

Fenomena ini dapat dijelaskan dengan memeriksa cara kerja penerapan node tunggal: meningkatkan ukuran batch berkolerasi langsung dengan peningkatan pakar yang diaktifkan. Ketika ukuran batch adalah 1, rata-rata jumlah pakar yang diaktifkan per GPU adalah 2 * 8 / 8 = 2. Ketika batch cukup besar, semua pakar diaktifkan, yang berarti setiap GPU mengaktifkan 256 / 8 = 32 pakar. Mengaktifkan lebih banyak pakar berarti GPU perlu membaca lebih banyak parameter dari memori, yang secara signifikan meningkatkan tekanan bandwidth memori. Karena fase dekode model bahasa besar sudah mengalami hambatan oleh bandwidth memori daripada performa komputasi, meningkatkan ukuran batch dalam penerapan node tunggal secara signifikan mengurangi kecepatan output.

Perbandingan dari keempat konfigurasi penerapan multi-node (EP16, EP32, EP64, dan EP128) mengungkapkan bahwa nilai EP yang lebih tinggi menggeser Pareto Frontier ke arah peningkatan simultan dalam throughput dan kecepatan output.

Menggunakan nomor EP yang lebih tinggi berarti setiap GPU dialokasikan lebih sedikit pakar. Misalnya, EP128 berarti setiap GPU bertanggung jawab atas 256 / 128 = 2 pakar, sehingga tekanan bandwidth memori berkurang secara signifikan. Dengan kata lain, dengan menggunakan nomor EP yang lebih besar, kita secara efektif mendapatkan lebih banyak bandwidth memori. Ketika ukuran batch per GPU kurang dari 64, meningkatkan ukuran batch tidak secara signifikan mempengaruhi kecepatan komputasi pakar karena peningkatan jumlah input tidak secara signifikan meningkatkan tekanan bandwidth memori. Oleh karena itu, kita mengamati bahwa saat menggunakan EP128, meningkatkan ukuran batch tidak mempengaruhi kecepatan output secara signifikan.

Menariknya, pada ukuran batch yang lebih besar (64 permintaan per GPU), kami mengamati fenomena baru: throughput penerapan node tunggal sedikit lebih tinggi daripada penerapan multi-node. Sebagian alasannya adalah NVLink intra-node memiliki bandwidth yang lebih tinggi daripada InfiniBand antar-node. Bagian lainnya disebabkan oleh keterbatasan dalam implementasi kami. Kami akan menganalisis fenomena ini secara lebih rinci nanti.

Karena keterbatasan kapasitas memori, konfigurasi EP8 DP8 TP1 tidak dapat mencapai ukuran batch 128 per GPU, sehingga penerapan multi-node tetap menjadi pilihan yang lebih baik dalam skenario yang mengejar throughput lebih tinggi.

Tumpang Tindih Komputasi dan Komunikasi

Seperti yang diperkenalkan secara singkat di atas mengenai Paralelisasi Pakar, GPU menganggur selama komunikasi Lapisan MoE. Untuk mengurangi pemborosan dan menurunkan latensi, kita perlu menemukan tugas komputasi yang independen dari data untuk mengisi waktu kosong ini.

Jadwal untuk komputasi dan komunikasi tanpa tumpang tindih, tumpang tindih dispatch, dan pipeline lima tahap.

Bagian atas gambar di atas menunjukkan alur komputasi dari satu lapisan. Komputasi MoE bergantung pada Dispatch, dan komputasi lapisan berikutnya bergantung pada hasil Combine.

Kami menempatkan pakar bersama pada setiap GPU. Dengan cara ini, komputasi pakar bersama tidak memerlukan komunikasi AllToAll. Oleh karena itu, kita dapat melakukan komputasi pakar bersama segera setelah Dispatch Send, lalu menunggu Dispatch Recv selesai. Kami menyebut skema tumpang tindih ini "Dispatch Overlap".

Dispatch Overlap menawarkan implementasi yang mudah dan penerapan yang luas. Teknik ini menyembunyikan waktu komputasi pakar bersama di semua ukuran EP dan ukuran batch.

Untuk lebih meningkatkan tumpang tindih komputasi dan komunikasi, kami menggunakan batch mikro yang disebutkan dalam laporan teknis DeepSeek untuk memutuskan dependensi data. Seperti yang ditunjukkan pada bagian bawah gambar, kami membagi komputasi satu Lapisan Transformer menjadi 5 tahap:

Tahap 1: InputNorm, QKVProj, AppendKV, BMM

Tahap 2: BMM, Attn, OProj, PostNorm, Gate

Tahap 3: Dispatch Send, Pakar Bersama

Tahap 4: Dispatch Recv, MoE, Combine Send

Tahap 5: Combine Recv

Dalam 3 Lapisan Transformer Padat pertama, kami menggunakan seluruh batch. Dalam 58 Lapisan Transformer MoE berikutnya, kami membagi batch secara merata menjadi dua batch mikro. Kedua batch mikro tersebut dieksekusi secara bergantian, diimbangi oleh 3 tahap. Karena tidak ada dependensi data antara kedua batch mikro ini, kita dapat beralih ke komputasi batch mikro lain setelah Dispatch Send dan setelah Combine Send.

Rincian Latensi

Selanjutnya, kami membandingkan efek tumpang tindih melalui eksperimen, serta membandingkan perbedaan performa antara penerapan node tunggal EP8 dan penerapan multi-node EP128. Untuk memudahkan perbandingan, kami menggunakan GPU H100 untuk eksperimen berikut. Kami menggunakan TP1, ukuran batch 128 per GPU, panjang Kueri 2 per permintaan, dan panjang Cache KV 5000.

Latensi lapisan per kernel untuk konfigurasi paralel pakar dan tumpang tindih yang dibandingkan.

Gambar di atas menunjukkan total waktu yang dihabiskan untuk satu Lapisan Transformer MoE dan proporsi latensi dari berbagai jenis kernel. Kecuali untuk Dispatch, Combine, dan GroupGEMM, waktu eksekusi kernel lainnya harus sama dalam seri EP8, EP128 NoOverlap, dan EP128 DispatchOverlap karena ukuran batch-nya sama.

Tumpang Tindih

Mari kita bandingkan terlebih dahulu efek dari ketiga metode tumpang tindih tersebut. NoOverlap memakan waktu total 2667µs, DispatchOverlap memakan waktu 2651µs, menghemat 16µs atau hanya 0,6%. MicroBatch menunjukkan peningkatan yang sangat signifikan, memakan waktu 1896µs, percepatan 29%. Waktu Dispatch dan Combine berkurang secara signifikan. Dispatch menurun dari 593µs ke 367µs, dan Combine dari 1012µs ke 237µs.

Perhatikan bahwa untuk kernel komputasi, memecah batch ukuran 128 menjadi dua batch ukuran 64 meningkatkan total waktu eksekusi. Oleh karena itu, meskipun waktu yang dihabiskan untuk komunikasi berkurang sebesar 1001µs, total waktu hanya berkurang sebesar 771µs. Kami akan menjelaskan alasannya menggunakan model Roofline di bagian berikut.

Alasan inilah yang membuat microbatching tidak selalu meningkatkan performa.

Perubahan dalam kecepatan output dan throughput per node dengan micro-batching, diplot terhadap ukuran batch per GPU.

Gambar di atas menunjukkan peningkatan performa Microbatch dibandingkan dengan DispatchOverlap untuk ukuran batch 4-128. Ketika ukuran batch kurang dari 32, Microbatch menurunkan performa sebesar 5%-40%. Ketika ukuran batch lebih besar dari atau sama dengan 32, Microbatch dapat meningkatkan performa sebesar 10%-35%.

EP8 vs EP128

Mari kita kembali ke gambar sebelumnya dan membandingkan EP8 dan EP128 Microbatch. EP8 memakan waktu total 1802µs, sedikit lebih sedikit daripada 1896µs milik EP128. Selain peningkatan waktu eksekusi kernel yang dibawa oleh Microbatch yang disebutkan di atas, perbedaan utama ada pada GroupGEMM yang digunakan untuk komputasi MoE, dan dua kernel komunikasi, Dispatch dan Combine.

GroupGEMM EP8 memakan waktu 555µs, sedangkan GroupGEMM EP128 memakan waktu 270µs, berkurang setengahnya. Ini adalah keunggulan inti dari penerapan multi-node.

Sayangnya, waktu yang dihabiskan untuk komunikasi meningkat sebesar 213µs, yang sangat mengimbangi keunggulan GroupGEMM. Dalam uji performa terpisah dari kernel komunikasi kami, kami menemukan bahwa mereka hanya dapat mencapai separuh dari bandwidth Infiniband. Kami akan terus mengoptimalkan kernel komunikasi kami.

Kernel lain yang tertinggal secara signifikan adalah GEMM. Microbatch meningkatkan GEMM sebesar 95µs. Kami akan menganalisis GEMM secara lebih mendalam di bagian Roofline di bawah ini. Kami yakin bahwa implementasi GEMM saat ini belum mencapai performa optimal.

Roofline

Model Roofline adalah alat yang baik untuk menganalisis performa kernel. Sumbu horizontalnya adalah Intensitas Aritmatika, rasio FLOP terhadap byte I/O memori. Nilai sumbu horizontal dapat dihitung langsung dari semantik kernel. Sumbu vertikal mewakili performa yang dicapai, dihitung dengan membagi FLOP dengan latensi tolok ukur.

Batas atas teoretis dari performa kernel ditentukan secara langsung oleh spesifikasi GPU. Performa puncak FP8 H100 adalah 1979 TFLOP/s, direpresentasikan sebagai garis horizontal dalam model Roofline. Bandwidth memori H100 adalah 3,35 TB/s, direpresentasikan sebagai kemiringan garis yang melewati titik asal. Kedua garis tersebut memberikan batasan performa untuk kernel yang terikat komputasi dan terikat memori, masing-masing.

Di bawah ini, kami membahas performa kernel GroupGEMM dan GEMM.

GroupGEMM

Kernel GroupGEMM di MoE melakukan komputasi berikut: Terdapat g grup secara total, grup ke-i memiliki m_i token, melakukan perkalian matriks [m_i, k] x [k, n] -> [m_i, n]. Dalam pengujian performa, kami berasumsi bahwa jumlah token di setiap grup adalah sama, dilambangkan sebagai m_i = m. Maka jumlah FLOP untuk GroupGEMM adalah 2 * g * m * k * n, dan byte I/O memori adalah g * (m * k + n * k + m * n).

Dalam model DeepSeek-V3/R1, terdapat 256 pakar, dan setiap token dikirimkan ke 8 pakar untuk komputasi. Dengan asumsi ukuran batch 128, panjang kueri 2, menggunakan konfigurasi EP128 DP128, rata-rata jumlah token yang diterima oleh setiap pakar (yaitu, m) adalah 128 * 2 * 8 * 128 / 256 = 1024. Demikian pula, kita dapat menghitung m untuk konfigurasi dan ukuran batch lainnya.

Kami menggunakan implementasi GroupGEMM DeepGEMM untuk pengujian performa. Titik pengujian mencakup kombinasi konfigurasi EP8, EP16, EP32, EP64, EP128 dengan TP1 dan ukuran batch 1-128.

Kinerja GroupGEMM relatif terhadap garis batas atas komputasi dan bandwidth memori.

Gambar di atas menunjukkan model Roofline untuk GroupGEMM di bawah berbagai konfigurasi EP. EP yang berbeda sesuai dengan jumlah grup yang berbeda. Gambar tersebut mengilustrasikan garis performa yang hampir tumpang tindih, menunjukkan bahwa performa GroupGEMM didominasi oleh total jumlah token (direpresentasikan sebagai g * m).

Bintang-bintang menandai titik data yang sesuai dengan ukuran batch 128 per GPU untuk setiap konfigurasi EP. Membandingkan titik data bertanda bintang ini, kita dapat melihat bahwa saat EP meningkat (dan DP meningkat secara sinkron), jumlah token per pakar m juga meningkat. Pada EP8, m=128, sedangkan pada EP128, m=2048.

Saat m meningkat, Intensitas Aritmatika juga meningkat. Di sebagian besar konfigurasi, GroupGEMM dibatasi oleh bandwidth memori, sehingga meningkatkan m meningkatkan performa.

GEMM

Kernel GEMM sesuai dengan Proyeksi Linear dalam model, seperti Proyeksi Q/K/V/O. Untuk perkalian matriks [m, k] x [k, n] -> [m, n], jumlah FLOP adalah 2 * m * k * n, dan byte I/O memori adalah m * k + n * k + m * n. Kami juga dapat menguji latensi untuk ukuran batch 1-128.

Kinerja GEMM relatif terhadap garis batas atas komputasi dan bandwidth memori.

Gambar di atas menunjukkan model Roofline untuk GEMM di bawah berbagai konfigurasi EP. Kita dapat melihat bahwa performa GEMM dibatasi oleh bandwidth memori. Seiring bertambahnya ukuran batch, Intensitas Aritmatika juga meningkat, sehingga meningkatkan performa.

Microbatch

Saat menggunakan microbatching, kita membagi batch secara merata menjadi dua bagian. Dari kedua gambar di atas, kita dapat melihat bahwa ketika m menjadi m/2, efisiensi perkalian matriks menurun. Oleh karena itu, mengeksekusi dua perkalian matriks berukuran m/2 membutuhkan waktu lebih lama daripada mengeksekusi satu perkalian matriks berukuran m.

Multi-Token Prediction

Sepanjang artikel ini, kami berasumsi penggunaan Multi-Token Prediction (MTP) untuk dekode spekulatif. MTP mengubah panjang kueri per permintaan dari 1 menjadi 2. Untuk perkalian matriks, ini setara dengan mengubah m menjadi m * 2, sehingga meningkatkan efisiensi perkalian matriks. Di sisi lain, jika kita menggambar model Roofline untuk MLA, kita akan menemukan bahwa meningkatkan panjang kueri secara signifikan meningkatkan efisiensi kernel MLA.

Oleh karena itu, penggunaan MTP memainkan peran penting dalam efisiensi model.

Implementasi & pengoptimalan

Di bagian ini, kami akan memperkenalkan beberapa detail implementasi dan pengoptimalan untuk model DeepSeek-V3/R1 kami.

Kuantisasi

DeepSeek-V3/R1 dilatih secara natif pada FP8 menggunakan skema kuantisasi per-blok, dengan bobot dikuantisasi secara statis dan aktivasi dikuantisasi secara on-the-fly. Alih-alih menghitung faktor penskalaan per saluran atau per matriks secara statis, faktor penskalaan dihitung di seluruh vektor 128 elemen untuk aktivasi dan ubin 128x128 elemen untuk matriks, yang membatasi degradasi akurasi karena kuantisasi.

Di Perplexity, kami mengandalkan campuran kernel CUDA dan Triton untuk mendukung inferensi, dengan CUDA digunakan untuk kernel yang paling sensitif terhadap performa dan jarang dimodifikasi (seperti atensi dan GEMM), sementara Triton menerapkan berbagai macam kernel aktivasi, normalisasi, dan utilitas. Triton memungkinkan kami dengan cepat mengadaptasi kernel ke skema kuantisasi blok.

Untuk lapisan linear dan MoE, kami mencampur kernel Deep GEMM dengan kernel Triton GEMM kami sendiri, karena kami telah memperhatikan bahwa untuk dimensi matriks tertentu dan ukuran batch rendah, Split-K menghasilkan latensi yang lebih rendah. Jika lapisan yang tidak dikuantisasi melakukan perkalian (M, K) x (K, N), lapisan tersebut memerlukan faktor penskalaan (M x ceil_div(K, 128)) x (ceil_div(K, 128), ceil_div(N, 128)) untuk kuantisasi blok. Untuk kuantisasi blok, faktor penskalaan untuk aktivasi dihitung secara on-the-fly, alih-alih pra-kalibrasi. Karena faktor penskalaan aktivasi diagregasi hanya di sepanjang K dan bukan di sepanjang dimensi M, kernel hanya memerlukan sedikit perubahan untuk mendukung skema tersebut.

Komputasi SiLU dan perkalian secara batch, menunjukkan tensor masukan pakar, tensor keluaran, dan faktor penskalaan.

Fungsi aktivasi SiLU yang digunakan oleh DeepSeek-V3/R1 memerlukan perubahan substansial untuk mendukung grafik CUDA, kuantisasi blok, dan jumlah token yang dirutekan secara dinamis. Kuantisasi blok dapat menjadi masalah karena memperkenalkan reduksi horizontal, namun kernel telah memecah aktivasi di sepanjang dimensi tersembunyi mereka menjadi blok-blok yang terdiri dari 1024 elemen. Dalam satu blok, tensor yang akan dikuantisasi dipecah lebih lanjut dalam blok 128 untuk menghitung nilai mutlak terbesar, dengan Triton menghasilkan reduksi maks lintas-warp yang efisien, menambahkan overhead minimal.

Untuk mendukung perutean MoE di bawah grafik CUDA, kernel harus mengetahui informasi perutean yang menunjukkan jumlah token per pakar, alih-alih menjadwalkan pekerjaan berdasarkan ukuran buffer yang dialokasikan untuk menampung batas atas jumlah token. Kita tidak dapat memecah masalah berdasarkan dimensi tensor input, sehingga kita meluncurkan sejumlah besar kernel persisten yang membaca informasi perutean untuk menentukan berapa banyak token yang terisi dan membagi pekerjaan pemrosesan aktivasi di antara mereka secara dinamis.

Kami telah melakukan upstream beberapa kernel kami ke proyek FlashInfer dan di masa mendatang kami akan melakukan open-source pada lebih banyak kode kami.

Lapisan MLA

Kami menggunakan FlashInfer untuk komputasi MLA. FlashInfer mendukung pengaturan Tabel Halaman yang fleksibel dan performa yang sangat tinggi.

Kami menggabungkan q_a_proj dan kv_a_proj menjadi satu qkv_a_proj. Latensi menurun dari 15,4 µs + 14,8 µs = 30,2 µs menjadi 16,7 µs.

Kami mendekomposisi kv_b_proj menjadi dua matriks, k_b_proj dan v_b_proj. Kami menulis kernel BMM Terkuantisasi Blok FP8 untuk komputasi yang berkaitan dengan kedua matriks ini.

Grafik Cuda

Grafik Cuda dapat secara signifikan mengurangi overhead peluncuran kernel, yang sangat penting untuk performa. Kami membuat Grafik Cuda untuk setiap ukuran batch.

Sebelum mengembangkan Kernel AllToAll kami, kami menggunakan torch.all_to_all_single() untuk komunikasi AllToAll. Operasi ini mengharuskan semua GPU menggunakan ukuran batch yang sama. Namun, Grup DP yang berbeda dapat menjalankan ukuran batch yang berbeda.

Untuk memastikan all_to_all_single() kompatibel dengan berbagai Grup DP yang menggunakan ukuran batch yang berbeda, kami pertama-tama menggunakan operasi allreduce() sebelum setiap eksekusi model untuk mendapatkan ukuran batch maksimum di antara semua Grup DP. Kemudian kami membuat semua Grup DP menggunakan ukuran batch ini untuk berjalan.

Meskipun pendekatan ini memastikan kita dapat menggunakan Grafik Cuda, pendekatan ini memiliki tiga kerugian. Pertama, pendekatan ini memerlukan operasi allreduce() tambahan. Kedua, Grup DP dengan ukuran batch yang lebih kecil terpaksa melakukan padding. Ketiga, pendekatan ini membuat kode implementasi kita menjadi rumit.

Setelah menerapkan Kernel AllToAll kami sendiri, kami tidak lagi mengharuskan semua GPU menggunakan ukuran batch yang sama. Oleh karena itu, kami tidak lagi perlu melakukan operasi allreduce() tambahan atau melakukan padding ukuran batch.

Router MoE

Router MoE diimplementasikan dalam Triton, mengandalkan pengurutan yang dimodifikasi yang berasal dari pustaka standar yang juga melacak indeks dari elemen yang diurutkan. Implementasi ini dibagikan di semua model MoE, karena perutean Mixtral adalah kasus khusus dari rute DeepSeek di mana grup Top-K sama dengan grup dari semua pakar. Kernel jarang mengonsumsi indeks dan skor Top-K secara langsung, sedangkan skema pengiriman/penggabungan padat yang mengandalkan all-to-all memerlukan informasi perutean yang harus diagregasi per-pakar alih-alih berbasis per-token.

Pekerjaan Mendatang

Dalam pekerjaan mendatang, kami berencana untuk lebih mengoptimalkan performa model DeepSeek.

Pengoptimalan penting berikutnya adalah Disagregasi Prefill. Fase Prefill dan fase Decode dari model DeepSeek-V3/R1 memiliki karakteristik komputasi yang sangat berbeda. Keduanya dapat menggunakan strategi pengoptimalan dan skema penerapan yang berbeda.

Untuk Lapisan MLA, pada fase Decode, kami menggunakan Penyerapan Matriks untuk mengurangi jumlah FLOP dari komputasi MLA. Pada fase Prefill, pertama-tama memproyeksikan vektor laten ke dalam ruang K/V lalu melakukan komputasi dalam bentuk Multi-Head Attention (MHA) akan menghasilkan performa yang lebih baik.

Jika Prefill dan Decode berjalan pada GPU yang sama, untuk mengurangi dampak Prefill pada kecepatan output Decode, kami biasanya menggunakan prefill berpotongan untuk membagi kueri menjadi beberapa potongan untuk Prefill. Karena Cache KV menyimpan vektor laten, menjadi sulit untuk mengubah MLA ke dalam bentuk MHA.

Untuk Lapisan MoE, pada fase Decode, kami menggunakan EP dan DP sebesar mungkin untuk meningkatkan jumlah token input per pakar, sehingga meningkatkan performa GroupGEMM. Pada fase Prefill, karena jumlah token sudah cukup besar, GroupGEMM sudah terikat komputasi. Oleh karena itu, untuk Prefill, kita dapat menggunakan EP dan DP yang lebih kecil.

Jika Prefill dan Decode berjalan pada GPU yang sama, selama Grup DP apa pun melakukan Prefill, latensi Lapisan MoE pada semua GPU akan meningkat, yang secara signifikan mempengaruhi kecepatan output Decode.

Selain Disagregasi Prefill, kami juga berencana untuk mengoptimalkan aspek-aspek berikut:

Performa AllToAll: Kernel AllToAll kami saat ini hanya dapat mencapai 1/3 dari bandwidth Infiniband. Kami akan terus mengoptimalkan kernel ini.

Dekode spekulatif bergaya EAGLE: Dalam data di atas, kami berasumsi menggunakan dekode spekulatif untuk memprediksi 1 token. EAGLE dapat menggunakan struktur pohon untuk memprediksi beberapa token, meningkatkan panjang penerimaan, yang dapat secara signifikan meningkatkan kecepatan output.

Kernel GEMM: Dalam Model Roofline yang ditampilkan sebelumnya, kita dapat menemukan bahwa efisiensi kernel GEMM masih jauh dari batas teoretis. Kami akan terus mengoptimalkan kernel ini.

GB200 NVL72: Dalam solusi terbaru NVIDIA GB200 NVL72, 72 GPU Blackwell saling terhubung melalui NVLink berkecepatan tinggi. Untuk model arsitektur MoE, ini adalah peluang dan tantangan yang sangat besar.

Kesimpulan

Penerapan multi-node dari model DeepSeek MoE mencapai apa yang biasanya tidak mungkin dilakukan dengan LLM padat: secara bersamaan meningkatkan throughput dan latensi. Dengan mendistribusikan pakar ke lebih banyak GPU, kami mengurangi tekanan bandwidth memori per perangkat, memungkinkan pemrosesan yang lebih cepat dan throughput sistem yang lebih tinggi. Eksperimen kami menunjukkan konfigurasi EP128 mencapai throughput hingga 5x lebih tinggi pada kecepatan output yang setara dibandingkan dengan penerapan node tunggal.

Teknik tumpang tindih komputasi-komunikasi seperti micro-batching secara signifikan mengurangi overhead komunikasi multi-node, dengan implementasi kami menunjukkan percepatan hingga 40%. Kernel komunikasi AllToAll kustom kami dan implementasi kernel yang dioptimalkan telah memungkinkan penerapan yang efisien dari model parameter 671B.

Saat arsitektur MoE mendapatkan popularitas karena kemampuannya, strategi penerapan ini memberikan wawasan yang berharga untuk menskalakan model tersebut secara efisien.

Referensi

Laporan Teknis DeepSeek-V3

Ikhtisar Sistem Inferensi DeepSeek-V3/R1

Megatron-LM: Melatih Model Bahasa Multi-Miliar Parameter Menggunakan Paralelisasi Model

EAGLE: Pengambilan Sampel Spekulatif Memerlukan Pemikiran Ulang Ketidakpastian Fitur

Sitiran

BibTeX
@online{perplexity2025LowerLatencyAndHigherThroughputWithMultiNodeDeepseekDeployment,
  author = {{Perplexity} and Lequn Chen and Nandor Licker and Erin McKnight},
  title = {{Lower latency and higher throughput with multi-node DeepSeek deployment}},
  date = {2025-04-18},
  url = {https://perplexity.coolkeypoint.com/hub/blog/lower-latency-and-higher-throughput-with-multi-node-deepseek-deployment}
}