%CPU kullanım oranı yalan söylüyor
(brendanlong.com)- Sunucu performans sınırı genelde
topgibi izleme araçlarındaki % CPU kullanım oranı ile değerlendirilir, ancak gerçekte bu gösterge performansı doğrusal biçimde yansıtmaz - Ryzen 9 5900X ortamında stress-ng ile yapılan testte, %50 kullanım oranında gerçek iş yükü %60~100 seviyesine ulaşarak göstergeyle büyük fark göstermiştir
- Bunun başlıca nedeni hyper-threading ve turbo boost olup, mantıksal çekirdekler arasındaki kaynak paylaşımı ve saat hızı değişimi bu metriği çarpıtır
- Bu nedenle basit CPU kullanım oranı yerine, gerçekte işlenebilen iş yüküne ait benchmark ile mevcut throughput karşılaştırması daha doğru bir göstergedir
- CPU kullanım oranını doğrusal yorumlamak performans tahmininde büyük hatalara yol açtığından, sistem planlamasında benchmark temelli yaklaşım gerekir
Sunucudaki CPU kullanım oranı ile gerçek throughput arasındaki uyumsuzluk
- Sunucu işletirken birçok kişi sistemin azami kullanım oranına yaklaşıp yaklaşmadığını görmek ister
- Genelde
topgibi izleme araçları üzerinden ağ, bellek ve CPU kullanım oranları içinde en yüksek olan değere bakılır - Ancak pratikte CPU kullanım oranı ile işlenebilen iş yükünün doğrusal artmaması sorunu ortaya çıkar
Test ortamı ve yöntem
- Ubuntu masaüstü + Ryzen 9 5900X (12 çekirdek/24 thread) tabanlı deney
- Precision Boost Overdrive (Turbo) etkin
- stress-ng ile çeşitli yükler simüle edildi (1~24 worker, %1~100 kullanım oranı)
- Ölçüm metrikleri: sistemin raporladığı CPU kullanım oranı ve gerçek hesaplama miktarı (Bogo ops)
Sonuç özeti
- Genel CPU yükü: %50 kullanım oranında gerçek throughput %60~65
- 64 bit tamsayı işlemleri: %50 kullanım oranında throughput %65~85
- Matris işlemleri (Matrix math): %50 kullanım oranında throughput %80~100
- Gerçekte ek worker performansa katkı yapmasa da CPU kullanım oranı yükselir
Neden analizi
-
Hyper-threading
- 12 fiziksel çekirdek + 12 mantıksal çekirdek yapısı
- 12 veya daha az worker fiziksel çekirdeklere en uygun şekilde yerleştirilir, ancak bu sayı aşıldığında mantıksal çekirdek paylaşımı nedeniyle performans düşer
- Özellikle SIMD işlemlerinde (matris işlemleri) paylaşılan kaynaklar yüzünden performans artışı mümkün olmaz
-
Turbo boost
- Düşük yükte 4.9GHz → tam yükte 4.3GHz ile %15 saat hızı düşüşü
- CPU kullanım oranı hesaplamasında (= busy cycles / total cycles) çarpılma oluşur
- Payda (toplam cycle sayısı) küçüldükçe, kullanım oranındaki artış gerçek iş yüküne kıyasla olduğundan fazla görünür
Çıkarımlar
- CPU kullanım oranı mutlak bir performans göstergesi değildir
- Sunucu kapasite planlaması ve performans tahmini sırasında:
- 1. Benchmark ile azami throughput ölçülmeli
- 2. Gerçek zamanlı throughput izlenmeli
- 3. Bu iki değer karşılaştırılarak performans sınırına yaklaşılıp yaklaşılmadığı değerlendirilmelidir
- CPU mimarisi (AMD vs Intel), hyper-threading verimliliği ve turbo davranışı gibi etkenlere göre sapma büyük olabileceğinden işlemci bazında analiz gerekir
Sonuç
- CPU kullanım oranı yalnızca meşgul cycle oranıdır; gerçek işlem performansını doğru biçimde yansıtmaz
- Verimli kullanımda "%50 kullanım oranı" bile gerçekte azami performansın %80~100 seviyesine ulaşmış olabilir
- Bu nedenle performans izleme ve sistem planlaması, CPU kullanım oranı yerine benchmark temelli iş throughput’u etrafında şekillenmelidir
3 yorum
Gerçek HPC yapılandırma ortamlarında, kümeler temelde hyper-threading kapatılarak kurulur.
Hacker News görüşleri
CPU utilization’ın açıkça tanımlanmış bir niceliği ölçtüğünü düşünüyorum, yani yalan değil; ancak insanlar bundan kapasite modeli çıkarmaya çalışıp ekstrapolasyon yaptığında, gerçek ile beklenti arasındaki uyumsuzluğu yaşıyorlar
Hyperthreading (SMT) ve Turbo (clock scaling), doğrusal olmamaya yol açan birçok değişkenden yalnızca birkaçı; çekirdekler arasında paylaşılan bellek bant genişliği, interconnect kapasitesi ve işlemci önbelleği gibi kaynaklar da yük arttıkça “tükenen” kaynaklar
Yazılım tarafında da örneğin spinlock gibi olgular utilization üzerinde doğrusal olmayan etki yaratabilir
Çoğu CPU utilization metriği birkaç saniye ile 1 dakika arasında uzun ortalamalar alıyor, oysa gecikmeye duyarlı sunucuların performansı için önemli olan şeyler onlarca ila yüzlerce milisaniye içinde gerçekleşiyor
Bu yüzden çok saniyelik ortalama utilization, burst desenleriyle daha düzgün desenleri ayırt edemiyor
Ancak önerilen yaklaşım, yani “hata veya kabul edilemez gecikme oluşmadan önce sunucunun ne kadar işi kaldırabildiğini benchmark etmek” de özünde kararsız
Sunucunun kararsızlaşmaya başladığı noktayı bulmaya çalışırken ölçümler çok gürültülü hale geliyor ve kuyruk teorisi açısından da eşik noktasına yakınken bütün gürültü büyütülüyor
Ayrıca “sunucunun şu anda yaptığı iş miktarı” da çoğu zaman kararsız biçimde tanımlanıyor (RPS mi? İstek başına maliyet farklı, IPC de zamana göre değişiyor)
Sonuçta yük testi yaklaşımından çıkan güven aralıkları da, utilization metriklerinden ampirik model üretmekten çok farklı bir seviyede değil. Önkoşul, utilization’ı doğru ölçmek
Eğer perf ya da ftrace kullanmayı biliyorsanız, kısa süre içinde çok ayrıntılı işlemci metrikleri elde edip cache miss veya memory access nedeniyle oluşan CPU stall’ı, scheduler etkilerini ve çeşitli nedenleri doğrudan görebilirsiniz
Ama çoğu insan IPC, cache hit rate gibi metrikleri alsa bile bunlarla ne yapacağını bilmiyor
Sonunda çoğu insanın gerçekten önemsediği şey latency ve utilization
Kaba konuşursak, çoğu workload’da CPU utilization %80’i geçene kadar latency açısından büyük bir sorun olmuyor
Ama onun üstündeki utilization seviyelerinde workload latency’sini ciddi biçimde etkilemeye başlıyor
Latency’yi ne kadar etkilediğini anlamak için herkesin kendi workload’unu doğrudan ölçmesi gerekiyor
Latency’ye ne kadar duyarlı olunduğu da kuruma ve amaca göre değişiyor; bazen throughput optimizasyonu daha önemli olabilir
Hem latency hem throughput önemliyse ikisini de ölçüp uygun trade-off’a kendiniz karar vermelisiniz
Bence kilit noktalardan biri, “iş miktarı” tanımının kendisinin kaygan olması
Örneğin public-facing bir hizmette gerçek kullanıcı isteklerini mi ele alıyorsunuz, yoksa backend’de birikmiş verileri sakince hesaplayan bir AI eğitim workload’u mu çalıştırıyorsunuz, bu da farklı
Benim yaklaşımım şu: burst’lerin zaman zaman kaçınılmaz olduğu modern çok çekirdekli hyperthreaded CPU ortamlarında, CPU utilization %60 ise sunucuyu zaten “yüksek yüklü” sayıyorum
Günün önemli bir kısmında %60’ın üzerindeyse işi bölmenin uygun olduğunu düşünüyorum (özellikle kullanıcı isteklerine yanıt veren servisler için)
Eskiden bu tür eşikler sık sık cloud autoscaling düşünmeye itiyordu
Şimdi ise 100’den fazla çekirdekli sunucular yaklaşık 30 bin dolara kullanılabildiği için durum daha karmaşık
Bugün olsa, gerçek sunucu donanımını bir miktar fazla provision edip, gerektiğinde cloud service’lere (veya Kubernetes tabanlı dahili cloud’a) genişleyen hibrit bir yaklaşımı tercih ederdim
StackOverflow ilk dönemlerinde dedicated rack ve 10Gbps uplink ile muazzam trafiği verimli biçimde işletiyordu; bugün bunu yapmak daha da kolay
Sonuç olarak benim ölçütüm şu: CPU load %65’i 30 dakikadan uzun süre koruyorsa bunu zaten %100 etkili kullanım sayar ve kısa sürede ölçekleme gerektiğine karar veririm
Son IEEE Hot Interconnects keynote’unda Ultra Ethernet için latency tuning örnekleri de anıldı
2 saniye veya 5 saniye ölçeğinde düz görünse de, 100ms ölçeğinde bakınca frame burst olayı açıkça ortaya çıkıyor
Yani profiling’in ölçüm penceresi gerçek workload ile uyuşmuyorsa false negative yüzünden yanlış karar verilebilir ve bu da sorunu daha da kötüleştirir
Söylenenlere tamamen katılıyorum
CPU utilization’ın doğrusal olmama özelliği nedeniyle yüzde değeri gerçeklikle kopabiliyor
Yani yalan olan, yüzde birimiyle ölçülen CPU utilization’ın kendisi
Eğer iki workload da %100 CPU kullanım gösteriyor ama biri çok daha fazla güç tüketip CPU sıcaklığını ciddi biçimde yükseltiyorsa, gerçekte o workload’un daha fazla transistör kaynağı kullanıyor olması gerekmez mi diye düşündürüyor
CPU utilization kusursuz bir ölçü olmasa da pratikte faydalı şekilde kullanılabildi
Basit SRE deneyimimde bile CPU-bound task’lar için kuyruk teorisini CPU utilization verileriyle birleştirerek büyük etkinlikler öncesi sunucu kapasitesini hesapladım; daha “geleneksel” yaklaşımlar yerine çok daha muhafazakâr önerilen %CPU eşiğiyle bile sonuç çok daha maliyet etkin çıktı
Asıl mesele, biraz hatalı da olsa sahada işe yarayan bir ölçüyü fazla endişe etmeden kullanabilmek
Yine de production ortamında CPU utilization’ı bilerek hiçbir zaman %40’ın üstüne çıkarmadım; amaç çeşitli durumlar için biraz headroom bırakmaktı
Yazarın, “yüksek utilization’ı kuyruk teorisi açısından neden kaçınmak gerekir” sorusuna mantıksal temel sunmaması biraz eksik kalmış
Biraz gevşek bir metrik bile sahada yerinde kullanılırsa yeterli olabilir diye düşünüyorum
Örneğin her host için percentile metric’lerin basit ortalamasını ya da maksimumunu kullanmak veya host bazlı histogramları nihai toplulaştırmada percentile olarak hesaplamak arasında, pratikte büyük bir operasyon farkı görmedim
Matematiksel olarak kesin doğru-yanlış meselesine fazla takılan insanlar var ama gerçek operasyonlarda bunun etkisi çoğu zaman büyük olmuyor
%40 aslında oldukça gevşek, yani bol paylı bir utilization gibi geliyor
CPU% ile loadavg’i birlikte görmek sistem durumunu oldukça iyi anlatabilir diye düşünüyorum
loadavg yüksekken CPU% düşükse, ağ ya da I/O’ya takılmış olabilir veya system call vb. yüzünden bekliyor olabilir
Böyle bir durumda yalnızca CPU%’ye bakmak, sistemin zorlandığı yeri kaçırmanıza neden olabilir
Bu konuşmanın aynısını daha önce de duymuş gibi hissediyorum
Yazarın anlattıkları kuyruk teorisi kitaplarında onlarca yıldır tekrar edilen şeylerken, bunu sanki yeni keşfetmiş gibi yazması ilginç
Brendan Gregg’in "CPU Utilization is Wrong" yazısını hatırlattı
O blog yazısının ana fikri, CPU utilization’ın sadece CPU’nun meşgul olma “durumunu” ölçmesi ve hatta CPU bekleme halinde olsa bile onu busy sayması
IPC ise bu busy durumunun içinde saklı gerçek yararlı iş miktarını anlamaya yarayan ölçü
Eğer başka bir Brendan daha varsa birinin bunu açıklamasını isterim
Hyperthreading’in sağladığı performansı iki kat saymamak gerektiğini düşünüyorum
Gerçek hayatta hyperthreading iyi kullanılsa bile çoğu zaman yalnızca %15–30 kadar ek performans sağlıyor. Buna karşılık latency iki katına çıkabiliyor
Çekirdek utilization’ı yükseldiğinde clock düşüşü de mutlaka hesaba katılmalı; yani pratikte her zaman doğrusal olmamaya dikkat etmek gerekiyor
OS’nin sağladığı bilgilerle bile hyperthreading etkisini ve clock düşüşünü hesaba katarsanız çok daha doğru utilization tahmini yapılabilir
Bunun ötesinde cache/bellek bant genişliği sınırları veya pipeline stall’larının performans düşüşüne yol açmasını modellemek de bence imkânsız değil
İşi karmaşıklaştıran bir başka nokta da hyperthreading veriminin CPU mimarisine ve workload’a göre büyük farklılık göstermesi
Örneğin AMD’nin, özellikle yeni Zen tasarımlarında, uygulaması Intel’e göre çok daha bağımsız performans verebiliyor (bellek bant genişliği darboğazı olmadığı varsayımıyla)
Uygulama memory-bound ise hyperthreading ile daha iyi scaling görmek daha kolay
Daha önce üzerinde çalıştığım bir renderer projesi memory-bound olduğu için, yalnızca hyperthreading sayesinde %60–70 performans artışı görmüştük
Eskiden i7-3770K (4C/8T) üzerinde POV-Ray ile basit bir benchmark yapmıştım
1 thread → 2 thread tam iki kat, 2 → 4 yine iki kat, 4 → 8 ise ancak %15 artış sağlıyordu
Cache miss’i yapay olarak tekrar eden özel bir benchmark olsa, SMT’de neredeyse iki kat performans almak belki mümkün olabilir ama ne kadar gerçekçi emin değilim
Not: POV-Ray testini yeniden çalıştırasım geldi. Gerçekten çok uzun zaman olmuş
Yazar galiba %CPU utilization değerine göre performansın doğrusal artmadığını fark edip, buradan hareketle %CPU utilization’ın kendisinin “yalan” olduğu sonucuna varmış
Hyperthreading veya clock düşüşü olmasa bile, Apple silicon gibi değişkenlerin az olduğu düşünülen durumlarda da tam orantılı scaling çıkmıyor
Birden fazla çekirdeği aynı anda kullanmaya başladığınızda veri aktarım overhead’i gibi CPU dışı kaynak darboğazları sık sık sorun çıkarıyor ve benzer durumlar yaşanıyor
Yazarın kullandığı core terimi kafa karıştırıcı ve standart dışı
5900X’i 24 çekirdekli sistem diye anıyor ama gerçekte yapı, 12 fiziksel çekirdek ve 24 hyperthread’den oluşuyor
12 tanesi fiziksel çekirdek, kalan 12 tanesi ise bu çekirdeklerin her birine bağlı çalışan thread’ler
Instruction pipeline iki set olsa bile iç functional unit’ler ortak kullanılıyor
Yıllar önce, hyperthreading’i pek bilmeyen kardeşime bunu anlatmaya çalışırken aklımda kalan bir benzetme çıkmıştı: iki katlı tuvalet kâğıdı gibi
24’ünü birbirinden bağımsız ayıramazsın ama 12’liyi yaklaşık iki kat daha kullanışlı hale getirir
Geri bildirimi aldıktan sonra ifadeyi 12 core / 24 thread olarak düzelttim
Ama OS utilization’ı 24 core gibi gösterdiği için kafam karışmıştı
Intel yazılım tanımlı core’lar çıkarırsa ilginç olabilir
Hyperthreading’in mantıksal tersi gibi, iki veya daha fazla çekirdeğin kaynak paylaşarak “tek büyük çekirdeğe” dönüşmesi fikri
Aşağıdaki patent bağlantısına bakabilirsiniz
https://patents.google.com/patent/EP4579444A1/en
SMT çifti aynı tür workload çalıştırdığında, iç kaynak ve execution unit çekişmesi yüzünden SMT etkisi düşüyor
Eğer workload’lar tamamen farklıysa, boost tam tersine daha da yüksek olabilir
Artık modern CPU’larda P-core, E-core, turbo / turbo olmayan durumlar gibi değişkenler de işin içine girince tablo daha da karmaşık
SMT eklemenin watt başına performans artışı açısından turbo eklemekten daha etkili olduğuna dair bir çalışma görmüştüm; oldukça ilginçti
Gerçekten çok katıldığım bir konu
Bir gün sunucunun CPU’su %60’a ulaşmışken artık boşluk kalmadığını yöneticime anlatmaya çalıştım, ama bana biraz tuhaf bakmıştı
O sırada tam da böyle bir açıklama olsa çok işe yarardı
Kuyruk teorisini de beraber anlatırsanız etkisi daha büyük olur
%60’ın altında kuyruk gecikmesi pratikte ihmal edilebilir düzeyde
%70’i geçince gecikme belirginleşiyor, %80’den sonra ise neredeyse ikiye katlanıyor
Kendi deneyimimde P95 süreyi baz alarak hedefi %65’e koymuştum ve bu teorik eşiklerle neredeyse birebir örtüşüyordu
Sonuç olarak pratik kural şu: “%60 kullanım sınırı, %80’den sonra gecikme patlar”
Ama workload’a göre bu tamamen değişebilir
Özellikle sunucu CPU’larının 32 çekirdeğe çıktığı günümüzde daha da öyle
CPU utilization çoğu zaman beklendiği gibi çalışmıyor
Normalde bu tür yazılarda Linux/Windows üzerindeki utilization sayılarının doğruluğu tartışılacak sanırdım ama gerçekte RAM darboğazı yüzünden CPU’nun boşta beklediği ya da downclock olduğu durumlar da çok
Aslında CPU utilization, OS’nin (Windows ya da Linux) her çekirdeğe ne kadar thread atadığına bakıyor
Ama bu thread memcpy içinde %100 bekliyor olsa bile utilization olarak kayda geçiyor
Hyperthreading’in avantajı da şu: bir thread AVX/vector unit’e takılıyken, diğeri basit memcpy/RAM işine takılıysa, her iki tarafın unit kullanımını artırıp toplam performansı ve utilization’ı yükseltebiliyor
Sonuç olarak CPU Utilization, uzun süredir sezgisel olarak anlaşılması zor bir konu ve her seferinde yeni bir bakış açısı ortaya çıkıyor
Yine de her zaman ilginç bir konu
Asıl “yalan”, hyperthreaded core’ların gerçek core’larla tamamen aynı davrandığına inanmak
Sonuçta bunu 20 yılı aşkın süredir kullandığımız için, işin özünü unutuyor ve performans ölçümlerinin neden tuhaf çıktığını tekrar tekrar fark ediyoruz
Bir başka nokta da şu: işlemci temelde ya “çalışıyor”dur (%100) ya da “bekliyordur” (%0)
Araya bir yüzde koymak, sonuçta yalnızca belirli bir zaman aralığının ortalamasını vermek demek; bunu yeniden düşünmeye itiyor
Daha önce buna benzer bir konuşma yaşamıştım
Yönetici: CPU utilization %100 ise sunucuyu daha büyük bir instance’a taşımamız gerekmez mi diye sormuştu
Ben: “Peki ama CPU şu an gerçekten faydalı bir iş yapıyor mu?”
Sonuçta busy waiting de CPU utilization olarak yazıldığı için, gerçek yararlı işle ilgisiz biçimde sayı yükselebiliyor
Doğru bir ifade.