SORU
20 ŞUBAT 2015, Cuma


Neden hedef daha hızlı işlev, hedef'in daha iyidir?

50% olan bir uygulamada performans noktaları araştırıyorum hedef zaman onun(3). Uygulama 4-byte tamsayılar milyonlarca ekler diziler sıralanmış ve hedef verileri kaydırmak için kullandığı "Sağ" için sipariş eklenen değer için yer açmak için.

Benim beklentim kopyalama bellek, son derece hızlı ve şaşırmış olmamdı çok zaman hedef için harcanan. Ama o zaman hedef olduğunu bilmiyordum uygulanması gereken bölgeler, üst üste binen hareket ettiğinden yavaş bellek büyük sayfaları kopyalamak yerine sıkı bir döngü içinde. Bir küçük yazdım microbenchmark arasında performans farkı olup olmadığını öğrenmek için memcpy ve hedef, işlev, hedef'in eller aşağı kazanmak için bekliyor.

İki makine (ı5, core i7 core) benim kıyaslama yaptım ve hedef olduğunu gördüm memcpy daha aslında daha hızlı, daha yaşlı core i7 neredeyse iki kat daha hızlı! Şimdi bir açıklama arıyorum.

İşte benim kriter. Bu işlev, hedef'in ile 100 mb kopyalar ve sonra hedef 100 mb hakkında taşır; kaynak ve hedef üst üste. "Mesafeler"çeşitli kaynak ve hedef çalıştı. Her test 10 kat, ortalama çalıştırın. zaman yazdırılır.

https://gist.github.com/cruppstahl/78a57cdf937bca3d062c

Burada Core ı5 sonuçları (Linux 3.5.0-54-jenerik #81~precise1-Ubuntu vardır SMU x86_64 GNU/Linux, gcc 4.6.3 (Ubuntu/4.6.3-1ubuntu5 Linaro). Numarası parantez içinde mesafe (gap boyut) kaynak ve hedef arasında:

memcpy        0.0140074
memmove (002) 0.0106168
memmove (004) 0.01065
memmove (008) 0.0107917
memmove (016) 0.0107319
memmove (032) 0.0106724
memmove (064) 0.0106821
memmove (128) 0.0110633

Hedef SSE optimize edilmiş bir kod çevirici, geri kopyalama olarak uygulanır ön için. Donanım hazırlık önbellek verileri yüklemek için kullanır, ve kopya 128 XMM kayıt için bayt, hedefte saklar.

(memcpy-ssse3-back.S, çizgiler 1650 ff)

L(gobble_ll_loop):
    prefetchnta -0x1c0(%rsi)
    prefetchnta -0x280(%rsi)
    prefetchnta -0x1c0(%rdi)
    prefetchnta -0x280(%rdi)
    sub $0x80, %rdx
    movdqu  -0x10(%rsi), %xmm1
    movdqu  -0x20(%rsi), %xmm2
    movdqu  -0x30(%rsi), %xmm3
    movdqu  -0x40(%rsi), %xmm4
    movdqu  -0x50(%rsi), %xmm5
    movdqu  -0x60(%rsi), %xmm6
    movdqu  -0x70(%rsi), %xmm7
    movdqu  -0x80(%rsi), %xmm8
    movdqa  %xmm1, -0x10(%rdi)
    movdqa  %xmm2, -0x20(%rdi)
    movdqa  %xmm3, -0x30(%rdi)
    movdqa  %xmm4, -0x40(%rdi)
    movdqa  %xmm5, -0x50(%rdi)
    movdqa  %xmm6, -0x60(%rdi)
    movdqa  %xmm7, -0x70(%rdi)
    movdqa  %xmm8, -0x80(%rdi)
    lea -0x80(%rsi), %rsi
    lea -0x80(%rdi), %rdi
    jae L(gobble_ll_loop)

Neden hedef daha hızlı işlev, hedef'in? Bellek sayfaları kopyalamak için memcpy beklerdim döngü çok daha hızlı olmalıdır. En kötü durumda, işlev, hedef'in beklerdim hedef olarak hızlı olacak.

PS: benim arabam kod memcpy ile hedef yerini biliyorum. Biliyorum örnek kod C ve C karışımları . Bu soru gerçekten sadece akademik. amaçlar.

GÜNCELLEME 1

Testler bazı varyasyonları, çeşitli cevaplara göre yaptım.

  1. İki işlev, hedef'in çalışırken, daha sonra ikinci çalışma ilk olandan daha hızlıdır.
  2. Ne zaman "" memcpy hedef tamponu (memset(b2, 0, BUFFERSIZE...)) işlev, hedef'in ilk çalışması aynı zamanda daha hızlıdır. dokunaklı
  3. memcpy hala biraz hedef daha yavaştır.

İşte sonuçlar:

memcpy        0.0118526
memcpy        0.0119105
memmove (002) 0.0108151
memmove (004) 0.0107122
memmove (008) 0.0107262
memmove (016) 0.0108555
memmove (032) 0.0107171
memmove (064) 0.0106437
memmove (128) 0.0106648

Benim sonuç: dayalı bir yorum @Oliver Charlesworth, işletim sistemi işlemek fiziksel bellek olarak işlev, hedef'in hedef tampon erişilen için ilk defa (birisi bilir nasıl "kanıt" bunu lütfen ekleyin bir cevap!). Ayrıca @Paspaslar Petersson dediği gibi, hedef işlev, hedef'in daha önbellek daha yumuşak yaklaşıyor.

Tüm cevap ve yorumlar için teşekkürler!

CEVAP
20 ŞUBAT 2015, Cuma


memmove aramalar memcpy kaynak ve hedef tamamen farklı olsa da 2 128 bit ile birlikte bellek karıştırma. Nedense bu performans farkı için muhasebe: eğer aynı yere kopyalayın, memcpy belki azıcık daha hızlı, örneğin ideone.com: biter görürsünüz

memmove (002) 0.0610362
memmove (004) 0.0554264
memmove (008) 0.0575859
memmove (016) 0.057326
memmove (032) 0.0583542
memmove (064) 0.0561934
memmove (128) 0.0549391
memcpy 0.0537919

Pek bir şey olsa - geri bellek sayfasında zaten hatalı bir yazı olduğuna dair hiçbir kanıtçoketki ve kesinlikle zaman yarıya görmüyoruz... ama yanlış bir şey elma-elma göre memcpy gereksiz yere uzatıyor olduğunu göstermektedir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Easy Learn Tutorial

    Easy Learn T

    10 Kasım 2012
  • GenTechPC

    GenTechPC

    1 Temmuz 2007
  • The Warp Zone

    The Warp Zon

    24 AĞUSTOS 2007

İLGİLİ SORU / CEVAPLAR