GNU/Linux >> Belajar Linux >  >> Linux

Menggunakan halaman 1GB menurunkan kinerja

Intel cukup baik untuk menjawab masalah ini. Lihat jawaban mereka di bawah.

Masalah ini disebabkan oleh bagaimana sebenarnya halaman fisik dilakukan. Dalam hal halaman 1GB, memori bersebelahan. Jadi, segera setelah Anda menulis ke satu byte mana pun dalam halaman 1GB, seluruh halaman 1GB ditetapkan. Namun, dengan halaman 4KB, halaman fisik dialokasikan saat dan saat Anda menyentuh untuk pertama kalinya di setiap halaman 4KB.

for (uint64_t i = 0; i < size / MESSINESS_LEVEL / sizeof(*ptr); i++) {
   for (uint64_t j = 0; j < MESSINESS_LEVEL; j++) {
       index = i + j * size / MESSINESS_LEVEL / sizeof(*ptr);
           ptr[index] = index * 5;
   }
}

Di loop terdalam, indeks berubah dengan kecepatan 512KB. Jadi, peta referensi berurutan pada offset 512KB. Biasanya cache memiliki 2048 set (yaitu 2^11). Jadi, bit 6:16 pilih setnya. Namun jika Anda menggunakan offset 512 KB, bit 6:16 akan sama dengan memilih set yang sama dan kehilangan lokalitas spasial.

Kami akan merekomendasikan menginisialisasi seluruh buffer 1GB secara berurutan (dalam pengujian halaman kecil) seperti di bawah ini sebelum memulai jam untuk menghitung waktu

for (uint64_t i = 0; i < size / sizeof(*ptr); i++)
    ptr[i] = i * 5;

Pada dasarnya, masalahnya adalah dengan konflik yang ditetapkan yang mengakibatkan cache hilang jika halaman besar dibandingkan dengan halaman kecil karena offset konstan yang sangat besar. Saat Anda menggunakan offset konstan, pengujiannya benar-benar tidak acak .


Bukan jawaban, tetapi untuk memberikan detail lebih lanjut untuk masalah yang membingungkan ini.

Penghitung performa menunjukkan jumlah instruksi yang hampir sama, tetapi kira-kira dua kali lipat jumlah siklus yang dihabiskan saat halaman besar digunakan:

  • 4KiB halaman IPC 0.29,
  • 1GiB halaman IPC 0.10.

Angka-angka IPC ini mengatakan bahwa kode tersebut terhambat pada akses memori (IPC yang terikat CPU pada Skylake adalah 3 ke atas). Hambatan halaman besar semakin sulit.

Saya memodifikasi tolok ukur Anda untuk menggunakan MAP_POPULATE | MAP_LOCKED | MAP_FIXED dengan alamat tetap 0x600000000000 untuk kedua kasus untuk menghilangkan variasi waktu yang terkait dengan kesalahan halaman dan alamat pemetaan acak. Di sistem Skylake saya, 2MiB dan 1GiB lebih dari 2x lebih lambat dari halaman 4kiB.

Disusun dengan g++-8.4.0 -std=gnu++14 -pthread -m{arch,tune}=skylake -O3 -DNDEBUG :

[[email protected]:~/src/test] $ sudo hugeadm --pool-pages-min 2MB:64 --pool-pages-max 2MB:64
[[email protected]:~/src/test] $ sudo hugeadm --pool-pages-min 1GB:1 --pool-pages-max 1GB:1
[[email protected]:~/src/test] $ for s in small huge; do sudo chrt -f 40 taskset -c 7 perf stat -dd ./release/gcc/test $s random; done
Duration: 2156150

 Performance counter stats for './release/gcc/test small random':

       2291.190394      task-clock (msec)         #    1.000 CPUs utilized          
                 1      context-switches          #    0.000 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
                53      page-faults               #    0.023 K/sec                  
    11,448,252,551      cycles                    #    4.997 GHz                      (30.83%)
     3,268,573,978      instructions              #    0.29  insn per cycle           (38.55%)
       430,248,155      branches                  #  187.784 M/sec                    (38.55%)
           758,917      branch-misses             #    0.18% of all branches          (38.55%)
       224,593,751      L1-dcache-loads           #   98.025 M/sec                    (38.55%)
       561,979,341      L1-dcache-load-misses     #  250.22% of all L1-dcache hits    (38.44%)
       271,067,656      LLC-loads                 #  118.309 M/sec                    (30.73%)
           668,118      LLC-load-misses           #    0.25% of all LL-cache hits     (30.73%)
   <not supported>      L1-icache-loads                                             
           220,251      L1-icache-load-misses                                         (30.73%)
       286,864,314      dTLB-loads                #  125.203 M/sec                    (30.73%)
             6,314      dTLB-load-misses          #    0.00% of all dTLB cache hits   (30.73%)
                29      iTLB-loads                #    0.013 K/sec                    (30.73%)
             6,366      iTLB-load-misses          # 21951.72% of all iTLB cache hits  (30.73%)

       2.291300162 seconds time elapsed

Duration: 4349681

 Performance counter stats for './release/gcc/test huge random':

       4385.282466      task-clock (msec)         #    1.000 CPUs utilized          
                 1      context-switches          #    0.000 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
                53      page-faults               #    0.012 K/sec                  
    21,911,541,450      cycles                    #    4.997 GHz                      (30.70%)
     2,175,972,910      instructions              #    0.10  insn per cycle           (38.45%)
       274,356,392      branches                  #   62.563 M/sec                    (38.54%)
           560,941      branch-misses             #    0.20% of all branches          (38.63%)
         7,966,853      L1-dcache-loads           #    1.817 M/sec                    (38.70%)
       292,131,592      L1-dcache-load-misses     # 3666.84% of all L1-dcache hits    (38.65%)
            27,531      LLC-loads                 #    0.006 M/sec                    (30.81%)
            12,413      LLC-load-misses           #   45.09% of all LL-cache hits     (30.72%)
   <not supported>      L1-icache-loads                                             
           353,438      L1-icache-load-misses                                         (30.65%)
         7,252,590      dTLB-loads                #    1.654 M/sec                    (30.65%)
               440      dTLB-load-misses          #    0.01% of all dTLB cache hits   (30.65%)
               274      iTLB-loads                #    0.062 K/sec                    (30.65%)
             9,577      iTLB-load-misses          # 3495.26% of all iTLB cache hits   (30.65%)

       4.385392278 seconds time elapsed

Berjalan di Ubuntu 18.04.5 LTS dengan Intel i9-9900KS (yang bukan NUMA), RAM 4x8GiB 4GHz CL17 di semua 4 slot, dengan performance gubernur tanpa penskalaan frekuensi CPU, kipas pendingin cair maksimal tanpa pelambatan termal, prioritas FIFO 40 tanpa preemption, pada satu inti CPU tertentu tanpa migrasi CPU, banyak proses. Hasilnya mirip dengan clang++-8.0.0 penyusun.

Sepertinya ada sesuatu yang mencurigakan di hardware, seperti buffer penyimpanan per frame halaman, sehingga halaman 4KiB memungkinkan penyimpanan ~2x lebih banyak per unit waktu.

Akan menarik untuk melihat hasil untuk CPU AMD Ryzen 3.

Pada AMD Ryzen 3 5950X, versi halaman besar hanya 10% lebih lambat:

Duration: 1578723

 Performance counter stats for './release/gcc/test small random':

          1,726.89 msec task-clock                #    1.000 CPUs utilized          
                 0      context-switches          #    0.000 K/sec                  
                 0      cpu-migrations            #    0.000 K/sec                  
             1,947      page-faults               #    0.001 M/sec                  
     8,189,576,204      cycles                    #    4.742 GHz                      (33.02%)
         3,174,036      stalled-cycles-frontend   #    0.04% frontend cycles idle     (33.14%)
            95,950      stalled-cycles-backend    #    0.00% backend cycles idle      (33.25%)
     3,301,760,473      instructions              #    0.40  insn per cycle         
                                                  #    0.00  stalled cycles per insn  (33.37%)
       480,276,481      branches                  #  278.116 M/sec                    (33.49%)
           864,075      branch-misses             #    0.18% of all branches          (33.59%)
       709,483,403      L1-dcache-loads           #  410.844 M/sec                    (33.59%)
     1,608,181,551      L1-dcache-load-misses     #  226.67% of all L1-dcache accesses  (33.59%)
   <not supported>      LLC-loads                                                   
   <not supported>      LLC-load-misses                                             
        78,963,441      L1-icache-loads           #   45.726 M/sec                    (33.59%)
            46,639      L1-icache-load-misses     #    0.06% of all L1-icache accesses  (33.51%)
       301,463,437      dTLB-loads                #  174.570 M/sec                    (33.39%)
       301,698,272      dTLB-load-misses          #  100.08% of all dTLB cache accesses  (33.28%)
                54      iTLB-loads                #    0.031 K/sec                    (33.16%)
             2,774      iTLB-load-misses          # 5137.04% of all iTLB cache accesses  (33.05%)
       243,732,886      L1-dcache-prefetches      #  141.140 M/sec                    (33.01%)
   <not supported>      L1-dcache-prefetch-misses                                   

       1.727052901 seconds time elapsed

       1.579089000 seconds user
       0.147914000 seconds sys

Duration: 1628512

 Performance counter stats for './release/gcc/test huge random':

          1,680.06 msec task-clock                #    1.000 CPUs utilized          
                 1      context-switches          #    0.001 K/sec                  
                 1      cpu-migrations            #    0.001 K/sec                  
             1,947      page-faults               #    0.001 M/sec                  
     8,037,708,678      cycles                    #    4.784 GHz                      (33.34%)
         4,684,831      stalled-cycles-frontend   #    0.06% frontend cycles idle     (33.34%)
         2,445,415      stalled-cycles-backend    #    0.03% backend cycles idle      (33.34%)
     2,217,699,442      instructions              #    0.28  insn per cycle         
                                                  #    0.00  stalled cycles per insn  (33.34%)
       281,522,918      branches                  #  167.567 M/sec                    (33.34%)
           549,427      branch-misses             #    0.20% of all branches          (33.33%)
       312,930,677      L1-dcache-loads           #  186.261 M/sec                    (33.33%)
     1,614,505,314      L1-dcache-load-misses     #  515.93% of all L1-dcache accesses  (33.33%)
   <not supported>      LLC-loads                                                   
   <not supported>      LLC-load-misses                                             
           888,872      L1-icache-loads           #    0.529 M/sec                    (33.33%)
            13,140      L1-icache-load-misses     #    1.48% of all L1-icache accesses  (33.33%)
             9,168      dTLB-loads                #    0.005 M/sec                    (33.33%)
               870      dTLB-load-misses          #    9.49% of all dTLB cache accesses  (33.33%)
             1,173      iTLB-loads                #    0.698 K/sec                    (33.33%)
             1,914      iTLB-load-misses          #  163.17% of all iTLB cache accesses  (33.33%)
       253,307,275      L1-dcache-prefetches      #  150.772 M/sec                    (33.33%)
   <not supported>      L1-dcache-prefetch-misses                                   

       1.680230802 seconds time elapsed

       1.628170000 seconds user
       0.052005000 seconds sys

Linux
  1. Menggunakan nfsstat dan nfsiostat untuk memecahkan masalah kinerja NFS di Linux

  2. Git Pelengkapan otomatis?

  3. Bagaimana cara mempercepat kinerja situs web menggunakan solusi caching XCache?

  1. Menggunakan PHP di halaman html

  2. Menggunakan UFW sebagai Daftar Hitam IP

  3. Kekurangan Saat Menggunakan Chroot Dalam Komputasi Kinerja Tinggi?

  1. Menggunakan skrip Apache2Buddy untuk kinerja dan stabilitas

  2. Menggunakan Windows Performance Analyzer untuk memecahkan masalah kinerja

  3. Menggunakan iostat untuk memantau kinerja sistem di Linux (Contoh disertakan)