Kinerja memori lambat (dan tidak biasa) tidak terduga dan tidak dapat dijelaskan dengan Xeon Skylake SMP


27

Kami telah menguji server menggunakan 2x Xeon Gold 6154 CPU dengan motherboard Supermicro X11DPH-I, dan RAM 96GB, dan menemukan beberapa masalah kinerja yang sangat aneh di sekitar memori bila dibandingkan dengan berjalan dengan hanya 1 CPU (satu soket kosong), dual serupa CPU Haswell Xeon E5-2687Wv3 (untuk seri pengujian ini, tetapi Broadwell lainnya melakukan hal yang sama), Broadwell-E i7s, dan Skylake-X i9s (untuk perbandingan).

Diharapkan bahwa prosesor Skylake Xeon dengan memori lebih cepat akan bekerja lebih cepat daripada Haswell ketika datang ke berbagai fungsi memcpy dan bahkan alokasi memori (tidak tercakup dalam tes di bawah ini, karena kami menemukan solusi), tetapi dengan kedua CPU terpasang , Skylake Xeon tampil pada hampir setengah kecepatan sebagai Haswell Xeon, dan bahkan lebih sedikit jika dibandingkan dengan i7-6800k. Apa yang lebih aneh, adalah ketika menggunakan Windows VirtualAllocExNuma untuk menetapkan NUMA untuk alokasi memori, sementara fungsi penyalinan memori diharapkan berkinerja lebih buruk pada simpul jarak jauh dibandingkan dengan simpul lokal, fungsi penyalinan memori yang menggunakan register SSE, MMX, dan AVX berkinerja lebih baik. lebih cepat pada simpul NUMA jarak jauh daripada pada simpul lokal (apa?). Seperti disebutkan di atas, dengan Skylake Xeon,

Saya tidak yakin apakah ini bug pada motherboard atau CPU, atau dengan UPI vs QPI, atau tidak ada yang di atas, tetapi tidak ada kombinasi pengaturan BIOS yang memanfaatkan ini. Menonaktifkan NUMA (tidak termasuk dalam hasil tes) di dalam bios meningkatkan kinerja semua fungsi penyalinan menggunakan register SSE, MMX dan AVX, tetapi semua fungsi penyalinan memori biasa lainnya juga mengalami kerugian besar.

Untuk program pengujian kami, kami menguji keduanya menggunakan fungsi perakitan inline, dan _mmintrinsik, kami menggunakan Windows 10 dengan Visual Studio 2017 untuk semuanya kecuali fungsi perakitan, yang mana msvc ++ tidak akan mengkompilasi asm untuk x64, kami menggunakan gcc dari mingw / msys ke kompilasi file obj menggunakan -c -O2flag, yang kami sertakan dalam tautan msvc ++.

Jika sistem menggunakan NUMA node, kami menguji kedua operator baru untuk alokasi memori dengan VirtualAllocExNuma untuk setiap NUMA node dan melakukan rata-rata kumulatif 100 salinan memori penyangga dari 16MB masing-masing untuk setiap fungsi penyalinan memori, dan kami memutar alokasi memori tempat kami berada. antara setiap set tes.

Semua 100 sumber dan 100 buffer tujuan selaras 64 byte (untuk kompatibilitas hingga AVX512 menggunakan fungsi streaming) dan diinisialisasi satu kali untuk data tambahan untuk buffer sumber, dan 0xff untuk buffer tujuan.

Jumlah salinan yang dirata-rata pada setiap mesin dengan konfigurasi masing-masing bervariasi, karena jauh lebih cepat pada beberapa mesin, dan jauh lebih lambat pada yang lain.

Hasilnya adalah sebagai berikut:

Haswell Xeon E5-2687Wv3 1 CPU (1 soket kosong) pada Supermicro X10DAi dengan 32GB DDR4-2400 (10c / 20t, 25 L3 cache L3). Tapi ingat, benchmark berputar melalui 100 pasang buffer 16MB, jadi kita mungkin tidak mendapatkan hit cache L3.

---------------------------------------------------------------------------
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 2 cpu pada Supermicro X10DAi dengan ram 64GB

---------------------------------------------------------------------------
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

Skylake Xeon Gold 6154 1 CPU (1 soket kosong) pada Supermicro X11DPH-I dengan 48GB DDR4-2666 (18c / 36t, 24,75 MB cache L3)

---------------------------------------------------------------------------
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 2 CPU pada Supermicro X11DPH-I dengan 96GB DDR4-2666

---------------------------------------------------------------------------
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

Skylake-X i9-7940X pada ASUS ROG Rampage VI Extreme dengan 32GB DDR4-4266 (14c / 28t, 19,25 MB cache L3) (di-overclock ke 3,8GHz / 4,4GHz turbo, DDR pada 4040MHz, Target AVX Frekuensi 3737MHz, Target AVX- 512 Frekuensi 3535MHz, target cache frekuensi 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

Broadwell i7-6800k pada ASUS X99 dengan 24GB DDR4-2400 (6c / 12t, 15 MB cache L3)

---------------------------------------------------------------------------
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

Fungsi perakitan diturunkan dari fast_memcpy di xine-libs, sebagian besar digunakan hanya untuk membandingkan dengan pengoptimal msvc ++.

Kode Sumber untuk tes ini tersedia di https://github.com/marcmicalizzi/memcpy_test (agak lama untuk dimasukkan ke dalam pos)

Adakah orang lain yang mengalami hal ini atau apakah ada yang tahu mengapa ini terjadi?


Pembaruan 2018-05-15 13: 40EST

Jadi seperti yang disarankan oleh Peter Cordes, saya telah memperbarui tes untuk membandingkan prefetched vs tidak prefetched, dan NT menyimpan vs toko biasa, dan menyetel prefetching yang dilakukan di setiap fungsi ( saya tidak memiliki pengalaman yang berarti dengan penulisan prefetching, jadi jika Saya membuat kesalahan dengan ini, tolong beri tahu saya dan saya akan menyesuaikan tes yang sesuai. Prefetching memang memiliki dampak, jadi setidaknya itu melakukan sesuatu ). Perubahan ini tercermin dalam revisi terbaru dari tautan GitHub yang saya buat sebelumnya untuk siapa pun yang mencari kode sumber.

Saya juga telah menambahkan memcpy SSE4.1, karena sebelum SSE4.1 saya tidak dapat menemukan fungsi SSE _mm_stream_load(saya khusus menggunakan _mm_stream_load_si128), jadi sse_memcpydan sse2_memcpytidak dapat sepenuhnya menggunakan toko NT, dan juga avx_memcpyfungsi menggunakan fungsi AVX2 untuk memuat aliran.

Saya memilih untuk tidak melakukan tes untuk penyimpanan murni dan pola akses muatan murni, karena saya tidak yakin apakah penyimpanan murni bisa bermakna, karena tanpa memuat ke register mengaksesnya, data akan menjadi tidak berarti dan tidak dapat diverifikasi.

Hasil yang menarik dengan pengujian baru adalah bahwa pada pengaturan Socket Xeon Skylake Dual dan hanya pada pengaturan itu, fungsi toko sebenarnya secara signifikan lebih cepat daripada fungsi streaming NT untuk menyalin memori 16MB. Selain itu hanya pada pengaturan itu juga (dan hanya dengan LLC prefetch diaktifkan di BIOS), prefetchnta dalam beberapa tes (SSE, SSE4.1) mengungguli baik prefetcht0 dan no prefetch.

Hasil mentah dari tes baru ini terlalu lama untuk ditambahkan ke posting, sehingga mereka diposting pada repositori git yang sama dengan kode sumber di bawah results-2018-05-15

Saya masih tidak mengerti mengapa untuk streaming toko NT, simpul NUMA jarak jauh lebih cepat di bawah pengaturan Skylake SMP, meskipun menggunakan toko biasa masih lebih cepat daripada di simpul NUMA lokal


1
Belum punya kesempatan untuk mencerna data Anda, tetapi lihat juga Mengapa Skylake jauh lebih baik daripada Broadwell-E untuk throughput memori single-threaded? (membandingkan Skylake quad-core dengan Broadwell banyak-inti, dan melihat sisi buruk dari latensi memori / L3 yang lebih tinggi dalam sistem banyak-inti di mana bandwidth satu-inti dibatasi oleh konkurensi memori maks dalam satu inti, bukan oleh pengontrol DRAM.) SKX memiliki latensi tinggi / bandwidth rendah per inti ke L3 / memori secara umum, menurut pengujian Mysticial dan hasil lainnya. Anda mungkin melihat itu.
Peter Cordes

1
Apakah ada salinan Anda menggunakan toko NT? Saya baru saja memeriksa, dan semua salinan Anda kecuali MMX menggunakan prefetchntadan toko NT! Itu fakta penting besar yang Anda tinggalkan dari pertanyaan Anda! Lihat Enhanced REP MOVSB ​​untuk memcpy untuk diskusi lebih lanjut tentang rep movsbtoko vektor ERMSB vs NT vs. toko vektor biasa. Bermain-main dengan itu akan lebih berguna daripada MMX vs SSE. Mungkin cukup gunakan AVX dan / atau AVX512 dan coba NT vs. reguler, dan / atau tinggalkan prefetch SW.
Peter Cordes

1
Apakah Anda menyetel jarak prefetch untuk mesin SKX Anda? SKX mem- prefetchntabypass L3 dan juga L2 (karena L3 tidak inklusif), jadi lebih sensitif untuk mengambil jarak jauh (terlambat dan data harus datang jauh-jauh dari DRAM lagi, bukan hanya L3), jadi itu lebih "rapuh" ( sensitif terhadap penyetelan jarak yang tepat). Jarak prefetch Anda terlihat cukup rendah, di bawah 500 byte jika saya membaca ASM dengan benar. @ Mysticial's pengujian pada SKX telah menemukan bahwa prefetchntabisa menjadi pelambatan besar pada uarch itu ), dan dia tidak merekomendasikannya.
Peter Cordes

1
Anda pasti memiliki beberapa hasil menarik di sini, tetapi kami perlu menguraikannya dari berbagai efek . Memiliki angka baik dengan atau tanpa toko NT dapat memberi tahu kami sesuatu yang berguna tentang perilaku NUMA. Mengisi soket kedua bahkan memaksa L3 lokal ketinggalan untuk mengintip remote CPU, setidaknya di Broadwell / Haswell. Dual-socket E5 Xeon tidak memiliki filter pengintai. Saya pikir Emas Xeon lakukan memiliki filter snoop, karena mereka mampu beroperasi di lebih dari sistem dual-socket. Tapi saya tidak yakin seberapa besar itu, atau apa artinya: PI belum melakukan penyetelan memori pada multi-socket.
Peter Cordes

2
SKX adalah interkoneksi yang berbeda secara fundamental; jala, bukan cincin. Ini hasil yang menarik, tetapi tidak bisa dipercaya dan mungkin bukan tanda kesalahan konfigurasi. IDK, semoga orang lain yang lebih berpengalaman dengan perangkat keras dapat menjelaskan lebih banyak.
Peter Cordes

Jawaban:


0

Apakah ingatan Anda salah Peringkat? Mungkin papan Anda memiliki beberapa hal aneh dengan peringkat memori ketika Anda menambahkan CPU kedua itu? Saya tahu ketika Anda memiliki mesin Quad CPU mereka melakukan segala macam hal aneh untuk membuat memori bekerja dengan baik dan jika Anda memiliki memori peringkat yang salah kadang-kadang akan berfungsi tetapi jam kembali seperti 1/4 atau 1/2 kecepatan. Mungkin SuperMicro melakukan sesuatu di papan itu untuk membuat DDR4 dan Dual CPU menjadi Quad Channel dan menggunakan matematika yang serupa. Peringkat salah == 1/2 kecepatan.


Tampaknya tidak demikian, semua memori adalah 1R8, dan cocok dengan peringkat dari supermicro qvl untuk motherboard. Layak untuk dicentang!
Marc Micalizzi

Saya tahu ini adalah sistem yang sama sekali berbeda, tetapi inilah yang saya maksudkan juga. qrl.dell.com/Files/en-us/Html/Manuals/R920/… Anda akan mencatat bahwa persyaratan peringkat berubah ketika Anda menambah jumlah stik / CPU.
thelanranger
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.