Supermicro X11DPH-I anakartlı 2x Xeon Gold 6154 CPU ve 96GB RAM kullanan bir sunucuyu test ettik ve yalnızca 1 CPU (bir yuva boş) ile çalışırken, hafızayı çevreleyen çok garip performans sorunları bulduk, benzer çift İşlemci Haswell Xeon E5-2687Wv3 (bu test serisi için, ancak diğer Broadwells'ler benzer şekilde çalışır), Broadwell-E i7s ve Skylake-X i9s (karşılaştırma için).
Daha hızlı belleğe sahip Skylake Xeon işlemcilerinin çeşitli memcpy işlevlerine ve hatta bellek tahsisine gelince Haswell'den daha hızlı performans göstermesi beklenirdi. Skylake Xeons, Haswell Xeons ile neredeyse yarı hızda ve i7-6800k ile karşılaştırıldığında daha da az performans gösteriyor. Hatta yabancı olan, Windows VirtualAllocExNuma'yı bellek tahsisi için NUMA düğümünü atamak için kullanırken, düz bellek kopyalama işlevleri uzaktaki düğümde yerel düğüme kıyasla beklenenden daha kötü performans gösterirken, SSE, MMX ve AVX kayıtlarını kullanan bellek kopyalama işlevleri çok daha fazla uzak NUMA düğümünde yerel düğümden daha hızlı (ne?). Yukarıda belirtildiği gibi, Skylake Xeons ile
Bunun anakartta veya CPU'da mı yoksa UPI vs QPI'de mi yoksa yukarıdakilerin hiçbirinde bir hata mı olduğundan emin değilim, ancak BIOS ayarlarının hiçbiri boşuna görünmüyor. Bios'ta NUMA'yı (test sonuçlarına dahil edilmez) devre dışı bırakmak, SSE, MMX ve AVX kayıtlarını kullanarak tüm kopyalama işlevlerinin performansını iyileştirir, ancak diğer tüm düz bellek kopyalama işlevleri de büyük kayıplara neden olur.
Test programımız için, hem satır içi montaj işlevlerini kullanarak test ettik, hem de _mm
kendimiz için, Windows 10'u Visual Studio 2017 ile birlikte kullandık, montaj işlevleri hariç her şey için, msvc ++ olarak x64 için asm'yi derlemiyor, mccw / msys'den gcc kullandık. -c -O2
msvc ++ linker içerisine dahil ettiğimiz flagları kullanarak bir obj dosyasını derleyin .
Sistem NUMA düğümleri kullanıyorsa, her iki operatöre de VirtualAllocExNuma ile her NUMA düğümü için yeni bellek tahsisi için sınama yapıyoruz ve her bir bellek kopyalama işlevi için her biri 16 MB'lık kümülatif ortalama 100 bellek arabellek kopyası yapıyoruz ve hangi bellek tahsisini kullandığımızı döndürüyoruz. Her test kümesi arasında.
Tüm 100 kaynak ve 100 hedef arabelleği 64 bayt hizalıdır (akış fonksiyonlarını kullanarak AVX512'ye uyumluluk için) ve kaynak tamponlar için artımlı verilere bir kez, hedef tamponlar için ise 0xff'ye sıfırlanır.
Her bir konfigürasyonda her makinede ortalama kopya sayısı, bazılarında çok daha hızlı ve bazılarında çok daha yavaş olduğu için değişmiştir.
Sonuçlar aşağıdaki gibidir:
Haswell Xeon E5-2687Wv3 Supermicro X10DAi'de 1 GB (1 boş yuva) 32 GB DDR4-2400 (10c / 20t, 25 MB L3 önbellek). Ancak unutmayın, referans noktası 100 çift 16 MB arabellek boyunca döner, bu yüzden muhtemelen L3 önbellek isabetlerini alamıyoruz.
---------------------------------------------------------------------------
Averaging 7000 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 2264.48 microseconds
asm_memcpy (asm) averaging 2322.71 microseconds
sse_memcpy (intrinsic) averaging 1569.67 microseconds
sse_memcpy (asm) averaging 1589.31 microseconds
sse2_memcpy (intrinsic) averaging 1561.19 microseconds
sse2_memcpy (asm) averaging 1664.18 microseconds
mmx_memcpy (asm) averaging 2497.73 microseconds
mmx2_memcpy (asm) averaging 1626.68 microseconds
avx_memcpy (intrinsic) averaging 1625.12 microseconds
avx_memcpy (asm) averaging 1592.58 microseconds
avx512_memcpy (intrinsic) unsupported on this CPU
rep movsb (asm) averaging 2260.6 microseconds
Haswell Dual Xeon E5-2687Wv3 2GB işlemci ile Supermicro X10DAi'de 64GB ram
---------------------------------------------------------------------------
Averaging 6900 copies of 16MB of data per function for VirtualAllocExNuma to NUMA node 0(local)
---------------------------------------------------------------------------
std::memcpy averaging 3179.8 microseconds
asm_memcpy (asm) averaging 3177.15 microseconds
sse_memcpy (intrinsic) averaging 1633.87 microseconds
sse_memcpy (asm) averaging 1663.8 microseconds
sse2_memcpy (intrinsic) averaging 1620.86 microseconds
sse2_memcpy (asm) averaging 1727.36 microseconds
mmx_memcpy (asm) averaging 2623.07 microseconds
mmx2_memcpy (asm) averaging 1691.1 microseconds
avx_memcpy (intrinsic) averaging 1704.33 microseconds
avx_memcpy (asm) averaging 1692.69 microseconds
avx512_memcpy (intrinsic) unsupported on this CPU
rep movsb (asm) averaging 3185.84 microseconds
---------------------------------------------------------------------------
Averaging 6900 copies of 16MB of data per function for VirtualAllocExNuma to NUMA node 1
---------------------------------------------------------------------------
std::memcpy averaging 3992.46 microseconds
asm_memcpy (asm) averaging 4039.11 microseconds
sse_memcpy (intrinsic) averaging 3174.69 microseconds
sse_memcpy (asm) averaging 3129.18 microseconds
sse2_memcpy (intrinsic) averaging 3161.9 microseconds
sse2_memcpy (asm) averaging 3141.33 microseconds
mmx_memcpy (asm) averaging 4010.17 microseconds
mmx2_memcpy (asm) averaging 3211.75 microseconds
avx_memcpy (intrinsic) averaging 3003.14 microseconds
avx_memcpy (asm) averaging 2980.97 microseconds
avx512_memcpy (intrinsic) unsupported on this CPU
rep movsb (asm) averaging 3987.91 microseconds
---------------------------------------------------------------------------
Averaging 6900 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 3172.95 microseconds
asm_memcpy (asm) averaging 3173.5 microseconds
sse_memcpy (intrinsic) averaging 1623.84 microseconds
sse_memcpy (asm) averaging 1657.07 microseconds
sse2_memcpy (intrinsic) averaging 1616.95 microseconds
sse2_memcpy (asm) averaging 1739.05 microseconds
mmx_memcpy (asm) averaging 2623.71 microseconds
mmx2_memcpy (asm) averaging 1699.33 microseconds
avx_memcpy (intrinsic) averaging 1710.09 microseconds
avx_memcpy (asm) averaging 1688.34 microseconds
avx512_memcpy (intrinsic) unsupported on this CPU
rep movsb (asm) averaging 3175.14 microseconds
Supermicro X11DPH-I'de 48 GB DDR4-2666 (18c / 36t, 24.75 MB L3 önbellek) bulunan Skylake Xeon Gold 6154 1 CPU (1 boş soket )
---------------------------------------------------------------------------
Averaging 5000 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 1832.42 microseconds
asm_memcpy (asm) averaging 1837.62 microseconds
sse_memcpy (intrinsic) averaging 1647.84 microseconds
sse_memcpy (asm) averaging 1710.53 microseconds
sse2_memcpy (intrinsic) averaging 1645.54 microseconds
sse2_memcpy (asm) averaging 1794.36 microseconds
mmx_memcpy (asm) averaging 2030.51 microseconds
mmx2_memcpy (asm) averaging 1816.82 microseconds
avx_memcpy (intrinsic) averaging 1686.49 microseconds
avx_memcpy (asm) averaging 1716.15 microseconds
avx512_memcpy (intrinsic) averaging 1761.6 microseconds
rep movsb (asm) averaging 1977.6 microseconds
Skylake Xeon Gold 6154 Supermicro X11DPH-I'de 96 GB DDR4-2666 ile 2 CPU
---------------------------------------------------------------------------
Averaging 4100 copies of 16MB of data per function for VirtualAllocExNuma to NUMA node 0(local)
---------------------------------------------------------------------------
std::memcpy averaging 3131.6 microseconds
asm_memcpy (asm) averaging 3070.57 microseconds
sse_memcpy (intrinsic) averaging 3297.72 microseconds
sse_memcpy (asm) averaging 3423.38 microseconds
sse2_memcpy (intrinsic) averaging 3274.31 microseconds
sse2_memcpy (asm) averaging 3413.48 microseconds
mmx_memcpy (asm) averaging 2069.53 microseconds
mmx2_memcpy (asm) averaging 3694.91 microseconds
avx_memcpy (intrinsic) averaging 3118.75 microseconds
avx_memcpy (asm) averaging 3224.36 microseconds
avx512_memcpy (intrinsic) averaging 3156.56 microseconds
rep movsb (asm) averaging 3155.36 microseconds
---------------------------------------------------------------------------
Averaging 4100 copies of 16MB of data per function for VirtualAllocExNuma to NUMA node 1
---------------------------------------------------------------------------
std::memcpy averaging 5309.77 microseconds
asm_memcpy (asm) averaging 5330.78 microseconds
sse_memcpy (intrinsic) averaging 2350.61 microseconds
sse_memcpy (asm) averaging 2402.57 microseconds
sse2_memcpy (intrinsic) averaging 2338.61 microseconds
sse2_memcpy (asm) averaging 2475.51 microseconds
mmx_memcpy (asm) averaging 2883.97 microseconds
mmx2_memcpy (asm) averaging 2517.69 microseconds
avx_memcpy (intrinsic) averaging 2356.07 microseconds
avx_memcpy (asm) averaging 2415.22 microseconds
avx512_memcpy (intrinsic) averaging 2487.01 microseconds
rep movsb (asm) averaging 5372.98 microseconds
---------------------------------------------------------------------------
Averaging 4100 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 3075.1 microseconds
asm_memcpy (asm) averaging 3061.97 microseconds
sse_memcpy (intrinsic) averaging 3281.17 microseconds
sse_memcpy (asm) averaging 3421.38 microseconds
sse2_memcpy (intrinsic) averaging 3268.79 microseconds
sse2_memcpy (asm) averaging 3435.76 microseconds
mmx_memcpy (asm) averaging 2061.27 microseconds
mmx2_memcpy (asm) averaging 3694.48 microseconds
avx_memcpy (intrinsic) averaging 3111.16 microseconds
avx_memcpy (asm) averaging 3227.45 microseconds
avx512_memcpy (intrinsic) averaging 3148.65 microseconds
rep movsb (asm) averaging 2967.45 microseconds
ASUS ROG Rampage VI Extreme'de Skylake-X i9-7940X , 32GB DDR4-4266 (14c / 28t, 19.25 MB L3 önbellek ile overclock edilmiş ) ( Extreme ile 3.8GHz / 4.4GHz turbo, DDR, 4040MHz'de DDR, Hedef AVX Frekans 3737MHz, Hedef AVX- 512 Frekans 3535MHz, hedef önbellek frekansı 2424MHz)
---------------------------------------------------------------------------
Averaging 6500 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 1750.87 microseconds
asm_memcpy (asm) averaging 1748.22 microseconds
sse_memcpy (intrinsic) averaging 1743.39 microseconds
sse_memcpy (asm) averaging 3120.18 microseconds
sse2_memcpy (intrinsic) averaging 1743.37 microseconds
sse2_memcpy (asm) averaging 2868.52 microseconds
mmx_memcpy (asm) averaging 2255.17 microseconds
mmx2_memcpy (asm) averaging 3434.58 microseconds
avx_memcpy (intrinsic) averaging 1698.49 microseconds
avx_memcpy (asm) averaging 2840.65 microseconds
avx512_memcpy (intrinsic) averaging 1670.05 microseconds
rep movsb (asm) averaging 1718.77 microseconds
24 GB DDR4-2400 (6c / 12t, 15 MB L3 önbellek) özellikli ASUS X99'da Broadwell i7-6800k
---------------------------------------------------------------------------
Averaging 64900 copies of 16MB of data per function for operator new
---------------------------------------------------------------------------
std::memcpy averaging 2522.1 microseconds
asm_memcpy (asm) averaging 2615.92 microseconds
sse_memcpy (intrinsic) averaging 1621.81 microseconds
sse_memcpy (asm) averaging 1669.39 microseconds
sse2_memcpy (intrinsic) averaging 1617.04 microseconds
sse2_memcpy (asm) averaging 1719.06 microseconds
mmx_memcpy (asm) averaging 3021.02 microseconds
mmx2_memcpy (asm) averaging 1691.68 microseconds
avx_memcpy (intrinsic) averaging 1654.41 microseconds
avx_memcpy (asm) averaging 1666.84 microseconds
avx512_memcpy (intrinsic) unsupported on this CPU
rep movsb (asm) averaging 2520.13 microseconds
Montaj işlevleri, çoğunlukla msvc ++ 's optimizer ile karşılaştırmak için kullanılan xine-libs içindeki fast_memcpy' den türetilmiştir.
Test için Kaynak Kodunu https://github.com/marcmicalizzi/memcpy_test adresinde bulabilirsiniz (yazıya koymak biraz uzun)
Başkası bununla karşılaştı mı, yoksa bunun neden olduğu konusunda bir fikri olan var mı?
2018-05-15 13: 40EST Güncellemesi
Peter Cordes'in önerdiği gibi, önceden kaydedilmiş vs önceden kaydedilmemiş ve NT mağazaları vs normal mağazaları karşılaştırmak için testi güncelledim ve her işlevde yapılan ön hazırlık ayarını yaptım (Ön hazırlık yazma konusunda anlamlı bir deneyimim yok. Bununla ilgili herhangi bir hata yapıyorum, lütfen bana bildirin ve testleri buna göre ayarlayacağım. Önceden getirmenin bir etkisi var, bu yüzden en azından bir şeyler yapıyor ). Bu değişiklikler, daha önce kaynak kodunu arayanlar için yaptığım GitHub bağlantısından yapılan en son revizyona yansıtılmıştır.
SSE4.1 I öncesinde herhangi bulamıyorum çünkü ben de bir SSE4.1 memcpy ekledik _mm_stream_load
(Ben özellikle kullanılan _mm_stream_load_si128
bu yüzden,) GGD fonksiyonlarını sse_memcpy
ve sse2_memcpy
NT mağazaları kullanarak tamamen olamaz ve de avx_memcpy
fonksiyon AVX2 işlevlerini kullanır Akış yükleme için.
Saf mağaza ve saf yük erişim düzenleri için bir test yapmamayı tercih ettim, çünkü saf mağazanın erişebildiği kayıtlara bir yük olmadan, verilerin anlamsız ve doğrulanamayacağından emin olabileceğimi bilmiyordum.
Yeni testle ilgili ilginç sonuçlar, Xeon Skylake İkili Soket kurulumunda ve yalnızca bu kurulumda, mağaza işlevlerinin 16 MB bellek kopyalama için NT akış işlevlerinden önemli ölçüde daha hızlı olmasıydı. Aynı zamanda sadece bu kurulumda (ve sadece BIOS'taki LLC önyüklemesi etkinken), bazı testlerde öndönükleme (SSE, SSE4.1) hem öndönüm0 hem de öndekileri geride bırakıyor.
Bu yeni testin ham sonuçları gönderiye eklemek için çok uzun, bu nedenle kaynak koduyla aynı git deposunda yayınlandılar. results-2018-05-15
NT mağazalarının akışında neden uzaktaki NUMA düğümünün Skylake SMP kurulumunda daha hızlı olduğunu hala anlamıyorum, normal mağazaların kullanımı yerel NUMA düğümünde olduğundan daha hızlı olsa da
prefetchnta
ve NT mağazaları! Sorunuzdan vazgeçtiğiniz çok önemli bir gerçek! ERMSB - NT vektörel mağazalar - normal vektörel mağazalar hakkında daha fazla tartışma için memcpy için bkz. Geliştirilmiş REP MOVSBrep movsb
. Bununla uğraşmak MMX'e karşı SSE'den daha faydalı olurdu. Muhtemelen sadece AVX ve / veya AVX512 kullanın ve NT ile normali deneyin ve / veya SW ön panelini dışarıda bırakın.
prefetchnta
L3'ü ve L2'yi atlar (çünkü L3 dahil değildir), bu nedenle ön tarama mesafesine daha duyarlıdır (çok geç ve verilerin tekrar DRAM'den gelmesi gerekir, sadece L3'ten değil), bu yüzden daha "kırılgan" ( doğru mesafeyi ayarlamaya duyarlı). Önceden alma mesafeleriniz, asm'ı doğru okuyorsam 500 baytın altında olsa da oldukça düşük görünüyor. @ Mysticial'ın SKX üzerinde yaptığı testler prefetchnta
bu alanda büyük bir yavaşlama olabileceğini buldu ) ve bunu önermiyor.