GNU/Linux >> Linux Esercitazione >  >> Linux

L'utilizzo di pagine da 1 GB riduce le prestazioni

Intel è stata così gentile da rispondere a questo problema. Vedi la loro risposta qui sotto.

Questo problema è dovuto al modo in cui le pagine fisiche vengono effettivamente impegnate. Nel caso di pagine da 1GB, la memoria è contigua. Pertanto, non appena si scrive su un byte qualsiasi all'interno della pagina da 1 GB, viene assegnata l'intera pagina da 1 GB. Tuttavia, con le pagine da 4 KB, le pagine fisiche vengono assegnate man mano che tocchi per la prima volta ciascuna delle pagine da 4 KB.

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

Nel ciclo più interno, l'indice cambia a un passo di 512 KB. Quindi, i riferimenti consecutivi vengono mappati con offset di 512 KB. In genere le cache hanno 2048 set (che è 2 ^ 11). Quindi, i bit 6:16 selezionano i set. Ma se procedi con offset di 512 KB, i bit 6:16 sarebbero gli stessi, finendo per selezionare lo stesso set e perdere la località spaziale.

Consigliamo di inizializzare l'intero buffer da 1 GB in sequenza (nel test della pagina piccola) come di seguito prima di avviare l'orologio per cronometrarlo

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

Fondamentalmente, il problema riguarda i conflitti tra insiemi che risultano in cache miss in caso di pagine enormi rispetto a pagine piccole a causa di offset costanti molto grandi. Quando usi offset costanti, il test non è davvero casuale .


Non una risposta, ma per fornire maggiori dettagli a questo problema sconcertante.

I contatori delle prestazioni mostrano un numero di istruzioni approssimativamente simile, ma circa il doppio del numero di cicli spesi quando vengono utilizzate pagine enormi:

  • Pagine da 4 KiB IPC 0,29,
  • Pagine da 1GiB IPC 0.10.

Questi numeri IPC indicano che il codice è bloccato sull'accesso alla memoria (l'IPC associato alla CPU su Skylake è 3 e superiore). Il collo di bottiglia di pagine enormi è più difficile.

Ho modificato il tuo benchmark per usare MAP_POPULATE | MAP_LOCKED | MAP_FIXED con indirizzo fisso 0x600000000000 in entrambi i casi per eliminare la variazione temporale associata a errori di pagina e indirizzo di mappatura casuale. Sul mio sistema Skylake 2MiB e 1GiB sono più di 2 volte più lenti delle pagine da 4kiB.

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

Girato su Ubuntu 18.04.5 LTS con Intel i9-9900KS (che non è NUMA), 4x8GiB 4GHz CL17 RAM in tutti e 4 gli slot, con performance regolatore per nessuna scalabilità della frequenza della CPU, ventole di raffreddamento a liquido al massimo per nessuna limitazione termica, priorità FIFO 40 per nessuna prelazione, su un core della CPU specifico per nessuna migrazione della CPU, esecuzioni multiple. I risultati sono simili con clang++-8.0.0 compilatore.

Sembra che ci sia qualcosa di sospetto nell'hardware, come un buffer di negozio per frame di pagina, in modo che le pagine da 4 KiB consentano ~2 volte più negozi per unità di tempo.

Sarebbe interessante vedere i risultati per le CPU AMD Ryzen 3.

Su AMD Ryzen 3 5950X la versione con pagine enormi è solo fino al 10% più lenta:

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. Utilizzo di PHP nelle pagine html

  2. Utilizzo di nfsstat e nfsiostat per risolvere i problemi di prestazioni NFS su Linux

  3. Svantaggio quando si utilizza un Chroot nel calcolo ad alte prestazioni?

  4. Git Completamento automatico?

  5. Utilizzo dello script Apache2Buddy per prestazioni e stabilità

Come monitorare le prestazioni di Linux utilizzando lo strumento systat

Utilizzo di Runit su Devuan

Come monitorare le prestazioni di Apache usando mod_status in Ubuntu

Come monitorare le prestazioni di Ubuntu utilizzando Netdata

Utilizzo di vmstat per risolvere i problemi di prestazioni in Linux

Miglioramento delle prestazioni utilizzando un file server statico aggiuntivo