Agner Fog'un optimizasyon kılavuzları mükemmel. Tüm yeni x86 CPU tasarımlarının (Intel Pentium'a kadar uzanan) mikro mimarisinde kılavuzları, talimat zamanlamaları ve belgeleri var. Ayrıca /programming//tags/x86/info adresinden bağlanan diğer bazı kaynaklara da bakın
Sadece eğlenmek için, bazı soruları cevaplayacağım (son Intel CPU'larının numaraları). Op seçimi, kodu optimize etmede ana faktör değildir (bölünmeyi engelleyemediğiniz sürece).
CPU'da tek bir çarpma işleminden bir kat daha yavaş mı?
Evet (2 gücü olmadan). (3-4x gecikme süresi, Intel'de saat başına yalnızca bir işlem.) Bundan kaçınmak için yolunuzun dışına çıkmayın, çünkü 2 veya 3 ekler.
Temel matematik ve kontrol akış opcodlarının hız özellikleri tam olarak nedir?
Eğer bilmek istiyorsanız Agner Sis talimat tabloları ve mikro mimari kılavuzu bakınız aynen : P. Koşullu sıçramalara dikkat edin. Koşulsuz sıçramalar (işlev çağrıları gibi) küçük bir ek yüke sahiptir, ancak çok fazla değildir.
İki opkodun yürütülmesi için aynı sayıda döngü gerekiyorsa, her ikisi de herhangi bir performans kazancı / kaybı olmadan birbirinin yerine kullanılabilir mi?
Hayır, başka bir şeyle aynı yürütme bağlantı noktası için rekabet edebilirler veya olmayabilirler. İşlemcinin paralel olarak çalışabileceği diğer bağımlılık zincirlerine bağlıdır. (Uygulamada, genellikle yararlı bir karar verilmez. Bazen, Intel CPU'larda farklı bağlantı noktalarında çalışan bir vektör kayması veya bir vektör karıştırması kullanabilirsiniz. PSLLDQ
vb.) karıştırma ünitesinde çalışır.)
X86 CPU performansı ile ilgili paylaşabileceğiniz diğer teknik ayrıntılar takdir edilmektedir
Agner Fog'un mikroarka belgeleri, Intel ve AMD CPU'ların boru hatlarını, bir döngünün yineleme başına tam olarak kaç döngü alması gerektiğini ve darboğazın uop verimi, bağımlılık zinciri veya bir yürütme bağlantı noktası için çekişme olup olmadığını yeterince ayrıntılı olarak açıklar. Gibi StackOverflow'daki benim bazı yanıtlar, bakın bu bir ya bu bir .
Ayrıca, http://www.realworldtech.com/haswell-cpu/ (ve önceki tasarımlar için benzer) CPU tasarımını seviyorsanız eğlenceli bir okuma.
İşte en iyi konuklarıma dayanarak bir Haswell CPU için sıralanmış listeniz. Yine de bu, bir şey için bir şey düşünmek için yararlı bir yol değil. Önbellek / dal tahmini etkileri genellikle baskındır, bu nedenle iyi kalıplara sahip olmak için kodunuzu yazın. Sayılar çok dalgalıdır ve verim bir sorun olmasa bile yüksek gecikmeyi hesaba katmaya veya başka şeylerin paralel olarak gerçekleşmesi için boruyu tıkayan daha fazla uops üretmeye çalışın. Esp. önbellek / şube numaraları çok oluşur. Döngü ile taşınan bağımlılıklar için gecikme, her yineleme bağımsız olduğunda verim önemlidir.
TL: DR bu sayılar, gecikme, yürütme-bağlantı noktası darboğazları ve ön uç verimi (veya şube özlüyorları gibi şeyler için duraklar) kadar "tipik" bir kullanım örneği için hayal ettiğim şeylere dayanarak oluşturulmuştur. ). Lütfen bu sayıları herhangi bir ciddi perf analizi için kullanmayın .
- 0,5 ila 1 Bitsel / Tamsayı Toplama / Çıkarma /
kaydırma ve döndürme (derleme zamanı sabit sayısı) /
bunların tüm vektör sürümleri (döngü verimi başına 1 ila 4, 1 döngü gecikmesi)
- 1 vektör min, maks, karşılaştır-eşit, karşılaştır-daha büyük (maske oluşturmak için)
- 1.5 vektör karıştırır. Haswell ve daha yenisinin sadece bir shuffle portu var ve bana ihtiyacınız varsa çok fazla karıştırmaya ihtiyaç duyuyor, bu yüzden daha az shuffle kullanmayı düşünmeyi teşvik etmek için biraz daha fazla ağırlık veriyorum. Özgür değiller, esp. bellekten bir pshufb kontrol maskesine ihtiyacınız varsa.
- 1.5 yükleme / depolama (L1 önbellek isabet. Gecikme süresi daha iyi)
- 1.75 Tamsayı Çarpma (Intel'de 1c tput başına 3c gecikme / bir, AMD'de 4c lat ve 2c tput'ta yalnızca bir adet). Küçük sabitler LEA ve / veya ADD / SUB / shift kullanarak daha ucuzdur . Ancak elbette derleme zamanı sabitleri her zaman iyidir ve genellikle başka şeylere de optimize edebilir. (Ve bir döngüde çarpma genellikle derleyici tarafından
tmp += 7
bunun yerine bir döngüde güç azaltılabilir tmp = i*7
)
- 1.75 bazı 256b vektör karıştırması (bir AVX vektörünün 128b şeritleri arasında veri taşıyabilen insns üzerinde ekstra gecikme). (Veya şerit geçişi karışıklıklarının daha fazla uops'a ihtiyaç duyduğu Ryzen'de 3 ila 7)
- 2 fp add / sub (ve aynı vektör versiyonları) (döngü geçişi başına 1 veya 2, 3 ila 5 döngü gecikmesi). Gecikme üzerinde tıkanırsanız yavaş olabilir, örneğin sadece 1
sum
değişkenli bir diziyi toplamak . (Bunu ağırlık ve kullanım durumuna bağlı olarak 1 kadar düşük veya 5 kadar yüksek olabilir).
- 2 vektör fp mul veya FMA. (x * y + z, FMA desteği etkinken derlerseniz bir katır veya bir eklenti kadar ucuzdur).
- 2 genel elemanların vektör elemanlarına (
_mm_insert_epi8
vb.) Yerleştirilmesi / çıkarılması
- 2.25 vektör int mul (16-bit elemanlar veya 8 x 8 -> 16-bit yapan pmaddubsw). Skylake üzerinde daha ucuz, skaler mul'dan daha iyi verim
- Değişken sayısına göre 2.25 kaydırma / döndürme (2c gecikme süresi, Intel'de 2c verim başına bir, AMD veya BMI2 ile daha hızlı)
- 2.5 Dallanma olmadan karşılaştırma (
y = x ? a : b
, veya y = x >= 0
) ( test / setcc
veya cmov
)
- 3 int-> float dönüşümü
- 3 mükemmel tahmin Kontrol akışı (tahmini şube, çağrı, dönüş).
- 4 vektör int mul (32 bit elemanlar) (2 uops, Haswell'de 10c gecikme süresi)
- 4 tamsayı bölme veya
%
derleme zamanı sabiti (2'nin gücü olmayan).
- 7 vektör yatay ops (örn.
PHADD
Bir vektör içine değer ekleme)
- 11 (vektör) FP Bölümü (10-13c gecikme, 7c verim başına bir veya daha kötüsü). (Nadiren kullanılırsa ucuz olabilir, ancak verim FP mul'den 6 ila 40x daha kötüdür)
- 13? Kontrol Akışı (kötü tahmin edilen dal, belki% 75 tahmin edilebilir)
- İnt int bölümü ( evet , aslında FP bölümünden daha yavaştır ve vektörleştirilemez). (derleyicilerin mul / shift / add ile sihirli bir sabit kullanarak bir sabite bölündüğünü unutmayın ve div / mod'un 2 güç ile çok ucuz olduğunu unutmayın.)
- 16 (vektör) FP sqrt
- 25? yük (L3 önbellek isabet). (önbellek özledim mağazaları yüklerden daha ucuzdur.)
- 50? FP trig / exp / log. Çok fazla exp / log'a ihtiyacınız varsa ve tam doğruluğa ihtiyacınız yoksa, daha kısa polinom ve / veya bir tabloyla hız için doğruluk ticaretini yapabilirsiniz. SIMD vectorizasyonu da yapabilirsiniz.
- 50-80? her zaman - öngörülen şube, 15-20 döngü maliyeti
- 200-400? yükle / sakla (önbellek özledim)
- 3000 ??? dosyayı dosyadan oku (işletim sistemi disk önbellek isabet) (sayıları burada oluşturarak)
- 20000 ??? disk okuma sayfası (OS disk önbellek kaçırma, hızlı SSD) (tamamen oluşturulmuş numara)
Tamamen tahminlere dayanarak uydurdum . Bir şeyler yanlış görünüyorsa, bunun nedeni farklı bir kullanım durumu veya bir düzenleme hatası düşündüğüm içindi.
Kaydırma sayısı değişken olduğunda daha hızlı tamsayı kaydırıcıları olması dışında AMD işlemcilerdeki göreceli maliyet benzer olacaktır. AMD Bulldozer ailesi CPU'lar çeşitli nedenlerden dolayı elbette çoğu kodda daha yavaştır. (Ryzen birçok konuda oldukça iyidir).
Bir şeyleri tek boyutlu bir maliyete kaynatmanın gerçekten imkansız olduğunu unutmayın . Önbellek özledikleri ve şube yanlış tahminleri dışında, bir kod bloğundaki darboğaz gecikme, toplam üop verimi (ön uç) veya belirli bir portun (yürütme portu) verimi olabilir.
Etraftaki kod CPU'yu diğer işlerle meşgul tutarsa FP bölümü gibi "yavaş" bir işlem çok ucuz olabilir . (vektör FP div veya sqrt her biri 1 uop, sadece kötü gecikme ve verim var. Sadece bölme birimini engelliyorlar, tüm yürütme portunu değil. Tamsayı div birkaç uops.) Yani sadece bir FP bölmeniz varsa her ~ 20 mul ve ekleme için ve CPU'nun yapacağı başka işler de var (örneğin, bağımsız bir döngü yinelemesi), o zaman FP div'in "maliyeti" bir FP mul ile aynı olabilir. Bu muhtemelen tüm yaptığınız zaman düşük iş hacmi olan bir şeyin en iyi örneğidir, ancak düşük toplam uops nedeniyle diğer kodlarla (gecikme bir faktör olmadığında) çok iyi karışır.
Tamsayı bölümünün çevre koduyla neredeyse aynı olmadığına dikkat edin: Haswell'de 9 uops, 8-11c verim başına bir ve 22-29c gecikme süresine sahip. (64 bit bölünmesi Skylake'de bile çok daha yavaştır.) Dolayısıyla, gecikme ve işlem sayıları FP div ile biraz benzer, ancak FP div sadece bir uop.
Verim, gecikme ve toplam uops için kısa bir insns dizisini analiz etme örnekleri için, SO cevaplarımdan bazılarına bakın:
İDK bu tür analizler de dahil olmak üzere SO cevapları yazarsa. Kendimi bulmak için çok daha kolay bir zamanım var, çünkü bu ayrıntıya sık sık girdiğimi biliyorum ve ne yazdığımı hatırlıyorum.