LLM sistemleri için RDMA noktadan noktaya iletişim
Yeni nesil LLM iletişim kalıpları için zarif araç
LLM sistemleri, eğitim ve çıkarımda yapılandırılmış paralel kalıplar için geleneksel olarak toplu iletişimlere (collective communications) güvenmiştir. Bununla birlikte, ayrıştırılmış çıkarım (disaggregated inference), Uzman Karışımı (MoE - Mixture-of-Experts) yönlendirmesi ve asenkron pekiştirmeli öğrenme ince ayarı (asynchronous reinforcement learning fine-tuning) gibi yeni ortaya çıkan iş yükleri, noktadan noktaya (point-to-point) iletişim esnekliğini gerektirmektedir.
En son araştırma makalemiz, NVIDIA ConnectX-7 ve AWS Elastic Fabric Adapter (EFA) dahil olmak üzere farklı Ağ Arayüz Denetleyicileri (NIC) arasında çalışan, taşınabilir RDMA tabanlı bir iletişim kütüphanesi olan TransferEngine'i tanıtmaktadır. Bunun etkinliğini Perplexity AI'daki üç üretim sisteminde gösteriyoruz:
Ayrıştırılmış Prefill ve Decode: Sayfalanmış yazma (paged writes) ve UVM izleyicileri (watchers) kullanan katman katman KvCache aktarımı; bu sayede prefill ve decode örneklerinin (instances) bağımsız olarak ölçeklenmesine olanak tanır.
2 Saniyenin Altında RL Sonrası Eğitimi için Ağırlık Aktarımı: Eğitim ve çıkarım düğümleri arasında son derece hızlı ağırlık senkronizasyonu.
AWS EFA Üzerinde Trilyon Parametreli Modellere Olanak Tanıma: Dağıt (scatter) ve bariyer (barrier) ilkellerini (primitives) kullanan, ConnectX-7 üzerinde son teknoloji gecikme sürelerine ve AWS EFA ile uyumlu ilk uygulanabilir çözüme ulaşan, düşük gecikmeli MoE dağıtım ve birleştirme işlemleri.
Bu makale, bu sistemlere güç veren iletişim kütüphanesi olan TransferEngine'in kendisine odaklanmaktadır. arXiv üzerindeki araştırma makalesinin tamamını okuyun ve GitHub üzerindeki kodu inceleyin.
Motivasyon
Toplu iletişimler (Collective communications), Tensör Paralelliği (Tensor Parallelism) ve Veri Paralelliği (Data Parallelism) gibi yapılandırılmış paralel kalıplarda mükemmeldir, ancak ortaya çıkan iş yüklerine uygulanabilirliklerini sınırlayan kısıtlamalar dayatırlar:
Sabit üyelik: Toplular, tüm katılımcılar arasında senkronize edilmiş bir kurulumla, başlatma zamanında küresel bir iletişim dünyası oluşturulmasını gerektirir. Ayrıştırılmış çıkarım için bu sorunludur, çünkü prefill ve decode örneklerinin sayısı trafik kalıplarına yanıt olarak dinamik olarak ölçeklenmelidir.
Tekdüze tensör şekilleri: Toplular, tüm katılımcıların aynı şekillere ve veri türlerine sahip tensörler alışverişinde bulunduğunu varsayar. MoE yönlendirmesinde, her uzmana gönderilen belirteç (token) sayısı veriye bağımlıdır ve çalışma zamanında keşfedilir; bu da yoğun all-to-all toplularını en kötü durum tampon boyutlarına dolgu (pad) yapmaya zorlar.
İşlem sıralaması: Toplu API'ler, uygulamaların yalnızca bir dizi işlemin tamamlandığını bilmesi gerektiğinde bile senkronize semantiği zorunlu kılar. Örneğin, KvCache aktarımında, prefill örneğinden decode örneğine tüm sayfalar herhangi bir sırayla gelebilir. Benzer şekilde, RL ağırlık güncellemelerinde, tüm ağırlık tensörleri sıralama kısıtlamaları olmaksızın bağımsız olarak aktarılabilir.
RDMA tabanlı noktadan noktaya iletişim, bu sınırlamaları doğası gereği ele alır, ancak üç engel benimsenmesini engellemiştir:
Kütüphane sınırlamaları: torch.distributed ve NCCL, Send/Recv gibi noktadan noktaya API'ler sağlasa da, bu işlemler hâlâ toplu semantiği ve sınırlamaları devralır.
Donanım çeşitliliği: Reliable Connection (RC) aktarımına sahip NVIDIA ConnectX NIC'ler, sıra ile teslimatı garanti eden en yaygın RDMA kurulumudur. AWS gibi bulut sağlayıcıları farklı donanımlar kullanır; Scalable Reliable Datagram (SRD) aktarımı ile Elastic Fabric Adapter (EFA), mesajları sırasız (out-of-order) olarak iletir. EFA ayrıca 400 Gbps bant genişliğine ulaşmak için dört adet 100 Gbps NIC'yi (veya iki adet 200 Gbps NIC'yi) birleştirmeyi gerektirir.
Yazılım taşınabilirliği: Mevcut RDMA kütüphaneleri sağlayıcı bağımlılığından (vendor lock-in) muzdariptir. DeepEP, yalnızca ConnectX'te bulunan GPU tabanlı RDMA (IBGDA) gerektirir. NVSHMEM, EFA üzerinde ciddi performans düşüşü sergiler. Mooncake ve NIXL gibi kütüphaneler EFA desteğinden yoksundur veya erken geliştirme aşamasındadır. Sonuç olarak, LLM çıkarımı için sağlayıcılar arası uygun bir çözüm bulunmamaktadır.
TransferEngine
TransferEngine, dört temel yetenek aracılığıyla bu engelleri ele alır:
Ortak aktarım varsayımları: Belirli bir NIC'yi hedeflemek yerine TransferEngine, yalnızca temel aktarımın güvenilir ancak sıralı olmadığını, yani hem RC hem de SRD aktarımları tarafından sağlanan garantilerin kesişimini varsayar.
ImmCounter senkronizasyonu: Mesaj sıralamasına dayanmadan çalışan, aynı kodun hem sıralı (RC) hem de sırasız (SRD) aktarımlarda çalışmasını sağlayan yeni bir tamamlama bildirimi ilkesi.
Çoklu NIC desteği: Bant genişliğini en üst düzeye çıkarmak için aktarımları otomatik olarak parçalara ayıran (shard), GPU başına birden fazla NIC'nin şeffaf yönetimi.
Minimal API yüzeyi: Karmaşık iletişim kalıpları oluşturmak için yeterli küçük bir işlem seti.
TransferEngine, GPU başına bir işçi konu (worker thread) oluşturur. Her işçi, donanım platformuna bağlı olarak 1 ila 4 RDMA NIC'sini koordine eden bir DomainGroup yönetir (tek bir ConnectX-7 400 Gbps sağlarken, EFA dört adet 100 Gbps adaptör veya iki adet 200 Gbps adaptör gerektirir). Bir DomainGroup içinde, her Domain donanıma özeldir ve kuyruk çifti (queue pair) yönetimini, iş gönderimini ve tamamlama yoklamasını (completion polling) ele alarak tek bir NIC'yi yönetir.
Her TransferEngine örneği, eş (peer) kimlik tespiti ve keşfi için tek bir ana adres (main address) sunar. Uzak eşler, ağ adreslerini kodlayan ve bant dışı (out-of-band) iletişim için serileştirilebilen NetAddr yapılarını (structs) değiş tokuş eder. Sistemdeki tüm eşler, GPU başına aynı sayıda NIC kullanmalıdır. Bu tekdüze yapılandırma, TransferEngine'in aktarımları akıllı bir şekilde parçalara ayırmasını sağlar: bir aktarım başlatıldığında, hem kaynak hem de hedef hangi NIC'lerin mevcut olduğunu tam olarak bilir ve tüm adaptörler arasında otomatik yük dengelemeyi etkinleştirir.
API Tasarımı
TransferEngine, temel RDMA arayüzlerinin karmaşıklığını soyutlayan minimal bir API sunar.
#[serde] struct NetAddr(Bytes);
#[serde] struct MrDesc{ ptr: u64, rkeys: Vec<(NetAddr, u64)> }
struct MrHandle(NonNull<c_void>); type Offset = u64;
struct Pages{ indices: Vec<u32>, stride: u64, offset: Offset }
struct PeerGroupHandle(u64);
struct ScatterDst{ len: u64, src: Offset, dst: (MrDesc,Offset)}
enum OnDone { Callback(fn () -> ()), Flag(Atomic<bool>) }
trait TransferEngine {
fn main_address() -> NetAddr;
// Memory Region Management
fn reg_mr(ptr, len, device) -> (MrHandle, MrDesc);
// Two-sided Send/Recv
fn submit_send(addr: NetAddr, msg: &[u8], cb: fn () -> ());
fn submit_recvs(len: u64, cnt: u64, cb: fn (&[u8]) -> ());
// One-sided Write
fn expect_imm_count(imm: u32, count: u32, cb: fn () -> ());
fn submit_single_write(len: u64, imm: Option<u32>
src: (MrHandle, Offset), dst: (MrDesc, Offset), OnDone);
fn submit_paged_writes(page_len: u64, imm: Option<u32>,
src: (MrHandle, Pages), dst: (MrDesc, Pages), OnDone);
// One-sided Write to a group of peers
fn add_peer_group(addrs: Vec<NetAddr>) -> PeerGroupHandle;
fn submit_scatter(h: Option<PeerGroupHandle>, OnDone,
imm: Option<u32>, src: MrHandle, dst: Vec<ScatterDst>);
fn submit_barrier(h: Option<PeerGroupHandle>, OnDone,
imm: u32, dst: Vec<MrDesc>);
// Watcher for CPU-GPU synchronization
fn alloc_uvm_watcher(cb: fn(u64,u64) -> ()) -> NonNull<u64>;
}API birkaç temel bileşenden oluşur:
Bellek Kaydı (Memory Registration)
RDMA işlemleri, veri aktarımından önce bellek bölgelerinin NIC'ye kaydedilmesini gerektirir. reg_mr fonksiyonu bir işaretçi (pointer), uzunluk ve cihaz alır ve iki tanıtıcı (handle) döndürür:
MrHandle: Aktarımlar için kaynak olarak kullanılan yerel bir tanıtıcı
MrDesc: Uzak eşlerin kayıtlı belleğe yazmasını sağlamak için onlarla değiş tokuş edilebilen serileştirilebilir bir tanımlayıcı (descriptor)
MrDesc yapısı, bellek bölgesine uzaktan erişim sağlayan bir uzak ağ adresi ve uzak anahtar listesi (NIC başına bir tane) içerir. Bu tasarım, çoklu NIC kurulumlarını doğası gereği ele alır.
İki Yönlü Gönder/Al (Two-Sided Send/Recv)
Küçük mesajlar ve RPC tarzı kontrol düzlemi mesajları için TransferEngine, submit_send ve submit_recvs sağlar:
submit_send: Mesajı NetAddr ile tanımlanan uzak bir eşe gönderir. Mesaj dahili olarak kopyalanır, böylece çağrı yapan (caller) tamponu hemen yeniden kullanabilir veya serbest bırakabilir.
submit_recvs: Bir alma tamponu havuzu yayınlar (posts). Bir mesaj geldiğinde, alınan verilerle birlikte bir geri çağrı (callback) tetiklenir. Tampon, geri çağrı tamamlandıktan sonra otomatik olarak havuza iade edilir.
Tek Taraflı Yazma (One-Sided Write)
Toplu veri aktarımları için TransferEngine, sıfır kopyalı (zero-copy) tek taraflı yazma işlemleri sağlar:
submit_single_write: Kaynaktan hedefe bitişik (contiguous) bir bölgeyi aktarır
submit_paged_writes: Dizinler (indices), adımlar (strides) ve uzaklıklar (offsets) tarafından belirtilen bitişik olmayan sayfaları aktarır
Her iki işlem de, tamamlama üzerine alıcıya atomik olarak iletilen isteğe bağlı 32 bitlik anında bir değer (immediate value) kabul eder.
Motor, bant genişliğini en üst düzeye çıkarmak için büyük aktarımları otomatik olarak birden fazla NIC arasında parçalara ayırır.
Eş Grupları ve Toplu İşlemler (Peer Groups and Bulk Operations)
Birden fazla eşi hedefleyen işlemler için (MoE yönlendirmesinde yaygındır) TransferEngine optimize edilmiş ilkeller sağlar:
add_peer_group: Hızlı arama için bir dizi eş adresini önceden kaydeder
submit_scatter: Gruptaki her eşe farklı veri dilimleri gönderir
submit_barrier: Tüm eşlere yalnızca anında (immediate-only) bildirim gönderir (sıfır baytlık aktarım)
Bu işlemler, dahili veri yapılarını önbelleğe alarak ve RDMA iş isteklerini şablonlaştırarak (templating) düşük gecikme süresi için optimize edilir ve tekrarlayan kurulum ek yükünü önler.
UVM İzleyicisi: GPU'dan CPU'ya Sinyalleşme
LLM sistemlerindeki temel bir zorluk, RDMA aktarımlarını GPU ilerlemesiyle koordine etmektir. İdeal olarak, veri aktarımı GPU çıktı ürettiği anda başlamalıdır, ancak CPU'dan GPU'yu yoklamak verimsizdir.
TransferEngine bunu UVM İzleyicileri (UVM Watchers) ile çözer: GPU çekirdekleri tarafından (CUDA grafikleri içinde bile) güncellenebilen ve GDRCopy kullanılarak CPU tarafından verimli bir şekilde yoklanabilen birleştirilmiş sanal bellek (unified virtual memory) konumları. Bir UVM izleyicisi ayrıldığında, GPU değeri her güncellediğinde çağrılan bir geri çağrı kaydedilir.
Bu, katman katman KvCache aktarımı gibi kalıpları etkinleştirir: her dönüştürücü (transformer) katmanı tamamlandıktan sonra GPU izleyiciyi artırır ve sonraki katmanlar hesaplamaya devam ederken o katmanın KvCache'sinin RDMA aktarımını tetikler.
Tamamlama Bildirimi (Completion Notification)
TransferEngine, hem başlatıcı tarafı (submit_write çağrısı yapan) hem de alıcı tarafı (Yazma işlemlerinin hedefi) için tamamlama bildirimi mekanizmaları sağlar.
Başlatıcı tarafı bildirimi: Bir yazma işlemi gönderildiğinde, çağrı yapan taraf bir geri çağrı fonksiyonu veya atomik bir bayrak (flag) aracılığıyla tamamlama üzerine bilgilendirilmeyi seçebilir. Bu bildirim, verilerin kaynak tampondan başarıyla aktarıldığını doğrular.
Alıcı tarafı bildirimi: Temel yenilik, 32 bitlik anında numaralarla indekslenen sayaçları izleyen bir bileşen olan ImmCounter'dır. Bir yazma işlemi anında bir değer taşıdığında, alıcının ImmCounter'ı veri tesliminde atomik olarak artırılır. expect_imm_count fonksiyonu, alıcının belirli bir anında değer hedef bir sayaca ulaştığında ateşlenen bir geri çağrı kaydetmesine olanak tanır. Sayaçlar GDRCopy aracılığıyla GPU ile şeffaf bir şekilde senkronize edilebilir, doğrudan yoklanabilir veya geri çağrılar aracılığıyla izlenebilir.
Bu alıcı tarafı mekanizması, mesaj sıralaması gerektirmeden güvenilir senkronizasyon sağlar. ConnectX NIC'lerde (RC aktarımı üzerinden sıra ile teslimatı garanti eder) ve EFA NIC'lerde (SRD aktarımı üzerinden mesajları sırasız iletir) eşit derecede iyi çalışır.
Uygulama
TransferEngine, gecikmeyi en aza indirmek ve yüksek verim (throughput) elde etmek için tahsisleri, konuları (threads) ve senkronizasyonu dikkatlice optimize ederek Rust ile uygulanmıştır. Motor, her DomainGroup için bir işçi konu oluşturur; her biri cihazların bağlı olduğu NUMA düğümündeki bir CPU çekirdeğine sabitlenerek (pinned) hem zamanlama hem de bellek erişim gecikmesini en aza indirir. Bir etki alanına (domain) özgü veri yapıları, belleğin doğru NUMA düğümünde ayrılmasını sağlamak için sabitlemeden sonra tahsis edilir. Bir işçi konu en fazla 4 Domain yönetirken (her biri tek bir NIC yönetir), başka bir özel konu UVM izleyicilerini güncellemek için GPU'yu yoklar. Konular arası iletişim (Cross-thread communication) kilitsiz kuyruklar (lock-free queues) aracılığıyla yapılır.
API, istekleri uygun cihazı sunan DomainGroup'a yönlendirir,incik birincisi aynı zamanda ana bilgisayara (host) hizmet eder. Sıkı bir döngüde (tight loop), etki alanı işçisi yeni işler için yoklama yapar ve yeni isteklerin gönderilmesine öncelik verir. Donanıma ve yapılandırmaya bağlı olarak, istekler parçalara ayrılarak mevcut Domain'ler arasında yük dengelemesi yapılır. Bileşik bir isteğin ilk Yazma işlemi hemen NIC'nin gönderim kuyruğuna yayınlanır. Yeni istekler tükendiğinde, işçi bekleyen işlemlerle devam eder ve donanım boru hattını (pipeline) doldurmak için yazmalar yayınlar. Ardından, tamamlanan aktarımları ve anında sayaç artışlarını sorgulamak için tamamlama kuyrukları yoklanır. Aktarım başına bildirimler iletmek için olaylar birleştirilir ve aktarım, tüm gruplar tarafından paylaşılan özel bir geri çağrı konusuna devredilir.
Bir DomainGroup içindeki parçalama esnektir. Aktarımlar dizine göre belirli NIC'leri hedefleyebilir. Tek bir Yazma bölünebilir. Tümü birden fazla Yazma işlemine dönüşen sayfalanmış aktarımlar, dağıt (scatter) ve bariyer işlemleri tüm NIC'ler arasında parçalanabilir.
Donanıma Özgü Optimizasyonlar
TransferEngine içindeki Domain'ler, kontrolleri altındaki donanım için özelleştirilmiş ve optimize edilmiştir:
AWS EFA: EFA uygulaması libfabric kullanır ve DomainGroup içinde NIC başına bir fabric etki alanı yönetir. Temel uygulama kararları ve optimizasyonlar şunları içerir:
Sıfır boyutlu yazmalar: EFA, sıfır boyutlu yazmalar için bile geçerli hedef tanımlayıcıları gerektirerek RDMA spesifikasyonundan sapar. Bu nedenle TransferEngine, tüm aktarımlar için geçerli tanımlayıcıları zorunlu kılar.
İş isteği şablonlaması: Yayınlamadan önce libfabric yapılarının ortak alanlarını önceden doldurur ve korur; bu da toplu aktarımlar ve eş grup işlemleri için işlem başına ek yükü azaltır
NVIDIA ConnectX-7: ConnectX-7 uygulaması, RC aktarımı ile libibverbs kullanır. Temel uygulama kararları ve optimizasyonlar şunları içerir:
El sıkışmaları için UD kuyruk çiftleri: Her Domain, RC bağlantı el sıkışmalarını değiş tokuş etmek için Güvenilmeyen Datagram (UD - Unreliable Datagram) kuyruk çifti kullanır.
Ayrı RC kuyruk çiftleri: Eş başına 2 RC kuyruk çifti oluşturur; biri iki yönlü Send/Recv işlemleri için, diğeri tek taraflı Write ve WriteImm işlemleri için. Bu ayrım gereklidir çünkü hem Recv hem de WriteImm tamamlamaları iş isteklerini yayınlama sırasıyla tüketir, bu da müdahale olmaksızın WriteImm'i desteklerken üst düzey Recv semantiğine izin verir.
İş isteği şablonlaması: Toplu aktarımlar ve eş grupları için iş isteği yapı地的 ortak alanlarını önceden doldurur.
İş isteği zincirleme (Chaining): ibv_send_wr'nin next işaretçisi aracılığıyla 4'e kadar iş isteğini birbirine bağlar, bu da NIC'ye gelen kapı zili (doorbell) çalım sayısını azaltır.
Gevşetilmiş sıralama (Relaxed ordering): NIC ile GPU belleği arasında sırasız PCIe işlemlerine izin vermek için IBV_ACCESS_RELAXED_ORDERING'yi etkinleştirir.
Sonuç
Farklı RDMA aktarımlarındaki garantilerin kesişimini hedefleyerek ve ImmCounter aracılığıyla sıradan bağımsız senkronizasyon sunarak TransferEngine, LLM sistemlerinde noktadan noktaya iletişim için taşınabilir bir temel sağlar. Kütüphane açık kaynaklıdır ve GitHub üzerinden edinilebilir; topluluğu, ölçeklenebilir makine öğrenimi sistemlerinde yeni ortaya çıkan iletişim kalıpları için bunu keşfetmeye ve üzerine inşa etmeye teşvik ediyoruz.
Alıntı
@online{perplexity2025RdmaPointToPointCommunicationForLlmSystems,
author = {{Perplexity} and Nandor Licker and Kevin Hu and Vladimir Zaytsev and Lequn Chen},
title = {{RDMA point-to-point communication for LLM systems}},
date = {2025-11-05},
url = {https://www.perplexity.ai/hub/blog/rdma-point-to-point-communication-for-llm-systems}
}