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.
- İki işlev, hedef'in çalışırken, daha sonra ikinci çalışma ilk olandan daha hızlıdır.
- Ne zaman "" memcpy hedef tamponu (
memset(b2, 0, BUFFERSIZE...)
) işlev, hedef'in ilk çalışması aynı zamanda daha hızlıdır. dokunaklı - 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
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.