SORU
27 Temmuz 2013, CUMARTESİ


Neden tanıtan bir işe yaramaz MOV talimatları x86_64 mecliste sıkı bir döngü o kadar hızlı olur?

Arka plan:

Gömülü assembly dili ile Pascal Bazı kod optimize ederken, MOV gereksiz bir yönerge fark ettim ve kaldırıldı.

Benim için sürpriz, un-gerekli talimat çıkarma programım neden olduaşağı yavaş.

Buldum, MOV keyfi yararsız talimatları performans artışı da sözlerine ekledidaha fazla bile.

Etkisi düzensiz ve değişikliklere yürütme sırasına göre:aynı önemsiz talimatları aktarılmışyukarı veya aşağı, tek bir çizgiylebir yavaşlama üretmek.

CPU optimizasyon ve düzene her türlü yapar bunu anlıyorum, ama bu kara büyü gibi görünüyor.

Veri:

Benim kod versiyonunu şartlı derlerüç önemsiz işlemleri2**20==1048576 kez çalışan bir döngü ortasında. (Çevre programı SHA-256 karma) hesaplar.

Oldukça eski makinem ((R) Core(TM)2 CPU 6400 @ 2.13 GHz) sonuçları:

avg time (ms) with -dJUNKOPS: 1822.84 ms
avg time (ms) without:        1836.44 ms

Bu program bir döngü içinde 25 kez, çalışma düzeni, rasgele değişen çalıştırın.

Alıntı:

{$asmmode intel}
procedure example_junkop_in_sha256;
  var s1, t2 : uint32;
  begin
    // Here are parts of the SHA-256 algorithm, in Pascal:
    // s0 {r10d} := ror(a, 2) xor ror(a, 13) xor ror(a, 22)
    // s1 {r11d} := ror(e, 6) xor ror(e, 11) xor ror(e, 25)
    // Here is how I translated them (side by side to show symmetry):
  asm
    MOV r8d, a                 ; MOV r9d, e
    ROR r8d, 2                 ; ROR r9d, 6
    MOV r10d, r8d              ; MOV r11d, r9d
    ROR r8d, 11    {13 total}  ; ROR r9d, 5     {11 total}
    XOR r10d, r8d              ; XOR r11d, r9d
    ROR r8d, 9     {22 total}  ; ROR r9d, 14    {25 total}
    XOR r10d, r8d              ; XOR r11d, r9d

    // Here is the extraneous operation that I removed, causing a speedup
    // s1 is the uint32 variable declared at the start of the Pascal code.
    //
    // I had cleaned up the code, so I no longer needed this variable, and 
    // could just leave the value sitting in the r11d register until I needed
    // it again later.
    //
    // Since copying to RAM seemed like a waste, I removed the instruction, 
    // only to discover that the code ran slower without it.
    {$IFDEF JUNKOPS}
    MOV s1,  r11d
    {$ENDIF}

    // The next part of the code just moves on to another part of SHA-256,
    // maj { r12d } := (a and b) xor (a and c) xor (b and c)
    mov r8d,  a
    mov r9d,  b
    mov r13d, r9d // Set aside a copy of b
    and r9d,  r8d

    mov r12d, c
    and r8d, r12d  { a and c }
    xor r9d, r8d

    and r12d, r13d { c and b }
    xor r12d, r9d

    // Copying the calculated value to the same s1 variable is another speedup.
    // As far as I can tell, it doesn't actually matter what register is copied,
    // but moving this line up or down makes a huge difference.
    {$IFDEF JUNKOPS}
    MOV s1,  r9d // after mov r12d, c
    {$ENDIF}

    // And here is where the two calculated values above are actually used:
    // T2 {r12d} := S0 {r10d}   Maj {r12d};
    ADD r12d, r10d
    MOV T2, r12d

  end
end;

Kendiniz deneyin:

Kodu online eğer kendiniz denemek isterseniz at GitHub.

Soru:

  • Neden boşuna bir kayıt 10 ** içeriğini kopyalama performansını artırmak istiyorsunuz?
  • Neden aynı işe yaramaz talimat bazı satırlar, bir hızlanma, ve diğerleri üzerinde bir yavaşlama sağlayabilir mi?
  • Bu davranış, tahmin edilebileceği gibi bir derleyici tarafından istismar edilebilecek bir şey mi?

CEVAP
28 Temmuz 2013, Pazar


Hızlı geliştirme en olası nedeni bu

  • bir MOV ekleme farklı bellek adresleri sonraki talimatları vardiya
  • o taşındı talimatları önemli bir koşullu bir şube oldu
  • bu dal yanlış dal tahmin tabloda aliasing nedeniyle tahmin ediliyordu
  • şube hareket diğer elenen ve şube doğru tahmin edilmesine izin verdi

Senin Core2 her koşullu atlama için ayrı bir geçmiş kaydı tutmaz. Bunun yerine tüm koşullu atlar ortak bir tarih tutar. global branch prediction tek dezavantajı, tarihi farklı koşullu atlar birbiri ile alakasız ise alakasız bilgi ile seyreltilmiş.

Bu küçük branch prediction tutorial şube tahmin tamponlar nasıl çalıştığını gösterir. Önbellek arabellek şube yönergenin adresi alt kısmı tarafından dizine. Bu iki önemli ayrı dallar bit alt aynı paylaşım sürece iyi çalışıyor. Bu durumda, sen-sonunda birçok mispredicted dalları talimat boru hattı ve yavaş program tezgahları) neden aliasing ile.

Eğer şube mispredictions performansını nasıl etkilediğini anlamak istiyorsanız, bu mükemmel bir cevap bir göz atın: http://stackoverflow.com/a/11227902/1001643

Derleyiciler genellikle dalları diğer adı ve diğer isimleri anlamlı olup olmadığını bilmek için yeterli bilgi yok. Ancak, bu Bilgi Cachegrind VTune gibi araçlar ile çalışma zamanında belirlenebilir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Keith Anthe

    Keith Anthe

    26 NİSAN 2011
  • ParryGripp

    ParryGripp

    12 AĞUSTOS 2006
  • talkandroid

    talkandroid

    27 Mayıs 2010