Bir vLLM sunucusu, sekiz dakika boyunca nvidia-smi‘de %97 kullanım bildiriyor. Aynı anda token verimliliği çöküyor. Her iki ifade de, absürt bir şekilde, doğru. İşte dijital aldatmacanın temeli bu. NVIDIA’nın her yerde kullanılan GPU kullanım metriği, üretken işin bir ölçüsü değil. Asla. Bu sadece basit bir görev döngüsü sayacı. GPU’da bir şeylerin çalıştığı zamanı söyler, o şeyin çalışmaya değer olup olmadığını değil.
Bu absürtlükle, vLLM’deki bir gecikme artışının dahili bir tekrarını yaparken karşılaştık. Donanım mı? Bir TensorDock RTX 4090. Yazılım mı? vLLM 0.18.0, Qwen2.5-0.5B-Instruct ile çalışıyor. Sekiz dakika boyunca gösterge paneli sağlık tablosu gibiydi. Nvidia-smi %92-99 arasında gidip geldi, ortalama %97. Fanlar homurduyor, bellek stabildi, güç çekişi 320W’da sabitti. Her şey yolunda, değil mi?
Yanlış.
Suçlu, mütevazı bir istek: n_completions=8 ve logprobs=20 eşleştirmesi. Bu canavar, her kod çözme adımını sekiz ayrı sekansa genişletiyor, her biri tam kelime haznesi softmax gerektiriyor. Token başına 150.000’den bahsediyoruz. Bu devasa isteklerin her biri, eşzamanlı planlanmış diğer tüm istekleri 9-11 saniye boyunca rehin aldı. GPU meşguldü, evet, ama kullanıcı tarafından görülmeyen çöp yığınıyla meşguldü. Verimlilik? Çökmüştü.
Bu marjinal bir senaryo değil. Bu, tek teşhis aracınız süslü bir kronometre olduğunda öngörülebilir sonuçtur.
NVIDIA’nın kendi dokümantasyonu GPU-Util’ı şöyle tanımlıyor: “Geçmiş örnekleme süresi boyunca GPU üzerinde bir veya daha fazla çekirdeğin çalıştığı zaman yüzdesi.” Görev döngüsü. Hepsi bu. Çekirdeğin verimli olup olmadığı, darboğaz olup olmadığı veya diğer işlemleri aktif olarak engelleyip engellemediği konusunda sıfır içgörü sunar. Bu, spor salonunda kaç saat geçirdiğinizle övünmek gibidir, ağırlık kaldırıp kaldırmadığınızı veya sadece tavana bakıp bakmadığınızı söylemeden.
NVIDIA’nın daha gelişmiş araç seti olan DCGM, SM_ACTIVE ve MEM_COPY_UTIL gibi sayaçlarla daha ince granülerlik sunar. Bunlar bir nebze yardımcı olur. Ancak zirve potansiyelinin %5’inde çalışan bir çekirdek 100 milisaniye boyunca o aralık için %100 SM_ACTIVE kaydeder. Gösterge paneli kayıtsız kalır.
Bu deseni çeşitli iş yüklerinde inceledik. Yüksek kullanım, düşen verimlilik ve sanki bir Sihirli 8 Topu olan bir gösterge paneli. Ortak nokta? Kök neden daha derinde yatıyor.
Olağan Şüpheliler: GPU’nuz Neden Meşgul Olduğunu Sanıyor?
-
Prefill/Decode Tango: vLLM, SGLang ve TGI gibi frameworkler, ön hazırlığı (girdi işleme) ve kod çözmeyi (çıktı üretimi) aynı donanımda gruplamaya çalışır. Ön hazırlık, kod çözmeden katlanarak daha fazla hesaplama gerektirdiğinde (uzun bağlamlarla yaygın bir senaryo), tek bir uzun bağlam isteği tüm daha kısa istekler için bir trafik sıkışıklığı haline gelir. Ön hazırlık çekirdekleri shader çekirdeklerini kapladığı için GPU %100
SM_ACTIVE‘de kalır. Bu sırada, bekleyen istekler için kod çözme gecikmesi sonsuza uzar. -
Dağıtık Eğitim Kilidi: Dört GPU’lu bir all-reduce işlemi hayal edin. Bir GPU yavaş kalırsa, diğerleri bekler. Bekleyen GPU’lar %100 kullanım gösterir çünkü beklemeyi yöneten çekirdek kendisi bir çekirdektir. Genel verimlilik, verimli olanlar değil, en yavaş sıralama tarafından belirlenir.
-
Dataloader Kilitlenmesi: Ana işlemde dizin permütasyonu yapan PyTorch’un
DataLoader‘ı, tek iş parçacıklı bir darboğaz haline gelebilir. GPU, aynı ileri çekirdeği tekrar tekrar çalıştırır, ancak bir sonraki yığının başlatılmasıcudaStreamSynctarafından engellenir. Çekirdek bağırır, ancak bir sonraki iş garajda sıkışmış durumdadır. -
CPU Çekirdek Kaosu: vLLM’nin motor döngüsü tek iş parçacıklıdır. Bir işletim sistemi bağlam anahtarı (komşu çekirdeğin çekirdek çalışması, can sıkıcı bir kesinti, kötü yönetilen bir cgroup)
cudaLaunchKernelçağrısını durdurabilir. P99cudaLaunchKernelsürelerinin 13,1 ms’ye (tipik 16,7us p50’den devasa bir sıçrama) uzadığını gördük, hepsi planlayıcı aksaklıklarından kaynaklanıyor. GPU, duraklamadan önce aktif olan çekirdeği çalıştırmaya devam eder, bu da kullanımın normal görünmesine neden olur. -
Bellek Bant Genişliği Erimesi: Sistemi SM’lerin işleyebileceğinden daha hızlı veriyle dolduran bir çekirdek %100
SM_ACTIVEraporlar. Peki gerçek kısıtlama ne? DRAM bant genişliği. Kullanım bir aldatmacadır; darboğaz bellek verimliliğidir.
Bu senaryoların her birinde, belirti iç karartıcı derecede tanıdıktır: yüksek kullanım, düşük verimlilik. Ancak neden daha derindeki katmanlarda gizleniyor.
Gerçek Darboğazı Bulmak
Peki, katmanları nasıl soyacaksınız? Toplam kullanımdan vazgeçin. Zor soruyu sorun: “GPU gerçekten neyi bekliyordu, saniye saniye?”
Bunu cevaplamak, aynı ana makineden zaman damgalı olarak senkronize edilmiş birden fazla kaynaktan gelen verileri ilişkilendirmeyi gerektirir:
- CUDA Çalıştırma Zamanı API Çağrıları:
libcudart.soüzerindeki uprobe’lar aracılığıylacudaLaunchKernel,cudaMemcpyAsync,cudaStreamSynchronizevecudaDeviceSynchronizegibi olayları izleyin. - CUDA Sürücü API Çağrıları:
libcuda.soüzerindeki uprobe’lar kullanarakcuLaunchKernelve ilgili sürücü düzeyindeki işlemleri izleyin. - Çekirdek Yürütme İzleri: Çalıştırılan gerçek çekirdeklerin içine dalın. CUPTI veya NVIDIA Nsight gibi araçlar, çekirdeğin kendisi içindeki çekirdek süresi, doluluk oranı ve kaynak kullanımı hakkında ayrıntılı profiller sağlayabilir.
-
Ana Makine Tarafı Etkinliği: CPU’yu göz ardı etmeyin. GPU sürücü etkileşimiyle ilgili CPU iş parçacığı etkinliğini, bağlam anahtarlarını ve sistem çağrılarını izleyin.
-
Bellek Bant Genişliği: DRAM bant genişliği kullanımını doğrudan ölçün. Bu genellikle DCGM veya belirli profilleme araçları aracılığıyla maruz kalır.
Bu iplikleri bir araya getirerek, nihayet üretken hesaplama yapan bir GPU ile sadece tekerleklerini döndüren bir GPU arasındaki farkı görebilirsiniz - %97 kullanımın uygun bir şekilde gizlediği bir ayrım.
Bu sadece teorik bir sorun değil; yüksek performanslı hesaplamada kalıcı, sinir bozucu bir gerçektir. Ve yapay zeka iş yükleri daha karmaşık hale geldikçe, basitlikteki kullanım sayacının ötesini görme yeteneği sadece faydalı değil, kesinlikle gerekli hale gelecektir.