GNU/Linux >> Tutoriels Linux >  >> Linux

L'utilisation de pages de 1 Go dégrade les performances

Intel a eu la gentillesse de répondre à ce problème. Voir leur réponse ci-dessous.

Ce problème est dû à la manière dont les pages physiques sont réellement validées. Dans le cas de pages de 1 Go, la mémoire est contiguë. Ainsi, dès que vous écrivez sur un octet de la page de 1 Go, la page entière de 1 Go est affectée. Cependant, avec des pages de 4 Ko, les pages physiques sont allouées au fur et à mesure que vous touchez pour la première fois dans chacune des pages de 4 Ko.

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

Dans la boucle la plus interne, l'index change à une vitesse de 512 Ko. Ainsi, les références consécutives sont mappées à des décalages de 512 Ko. Généralement, les caches ont 2048 ensembles (soit 2^11). Ainsi, les bits 6:16 sélectionnent les ensembles. Mais si vous progressez à des décalages de 512 Ko, les bits 6:16 seraient les mêmes, ce qui finirait par sélectionner le même ensemble et perdre la localité spatiale.

Nous vous recommandons d'initialiser l'intégralité de la mémoire tampon de 1 Go de manière séquentielle (dans le petit test de page) comme ci-dessous avant de démarrer l'horloge pour la chronométrer

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

Fondamentalement, le problème concerne les conflits d'ensemble entraînant des échecs de cache en cas de pages volumineuses par rapport aux petites pages en raison de décalages constants très importants. Lorsque vous utilisez des décalages constants, le test n'est vraiment pas aléatoire .


Pas une réponse, mais pour fournir plus de détails sur ce problème déroutant.

Les compteurs de performances affichent un nombre d'instructions à peu près similaire, mais environ le double du nombre de cycles passés lorsque des pages volumineuses sont utilisées :

  • Pages de 4 Kio IPC 0.29
  • 1 Gio de pages IPC 0.10.

Ces chiffres IPC indiquent que le code est goulot d'étranglement sur l'accès à la mémoire (l'IPC lié au processeur sur Skylake est de 3 et plus). D'énormes goulots d'étranglement de pages plus difficiles.

J'ai modifié votre benchmark pour utiliser MAP_POPULATE | MAP_LOCKED | MAP_FIXED avec adresse fixe 0x600000000000 dans les deux cas pour éliminer la variation temporelle associée aux défauts de page et à l'adresse de mappage aléatoire. Sur mon système Skylake, 2 Mio et 1 Gio sont plus de 2 fois plus lents que les pages de 4 Ko.

Compilé avec 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

Tourné sur Ubuntu 18.04.5 LTS avec Intel i9-9900KS (qui n'est pas NUMA), 4x8GiB 4GHz CL17 RAM dans les 4 emplacements, avec performance gouverneur pour aucune mise à l'échelle de la fréquence du processeur, ventilateurs de refroidissement liquide au maximum pour aucune limitation thermique, priorité FIFO 40 pour aucune préemption, sur un cœur de processeur spécifique pour aucune migration de processeur, plusieurs exécutions. Les résultats sont similaires avec clang++-8.0.0 compilateur.

On dirait que quelque chose ne va pas dans le matériel, comme un tampon de magasin par cadre de page, de sorte que les pages de 4 Ko permettent environ 2 fois plus de magasins par unité de temps.

Il serait intéressant de voir les résultats pour les processeurs AMD Ryzen 3.

Sur AMD Ryzen 3 5950X, la version pages volumineuses n'est que jusqu'à 10 % plus lente :

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. Utilisation de PHP dans les pages html

  2. Utiliser UFW comme liste noire IP

  3. Inconvénient lors de l'utilisation d'un chroot dans le calcul haute performance ?

  4. Auto-complétion Git ?

  5. Comment accélérer les performances d'un site Web à l'aide de la solution de mise en cache XCache ?

Comment surveiller les performances de Linux à l'aide de l'outil systat

Utiliser Runit sur Devuan

Comment surveiller les performances d'Apache à l'aide de mod_status dans Ubuntu

Comment surveiller les performances d'Ubuntu à l'aide de Netdata

Utilisation de vmstat pour résoudre les problèmes de performances sous Linux

Amélioration des performances en utilisant un serveur de fichiers statique supplémentaire