C'est un sujet qui me tient à cœur et qui a fait l'objet de recherches récentes. Je vais donc l'aborder sous plusieurs angles : l'histoire, quelques notes techniques (surtout académiques), les résultats des tests effectués sur mon boîtier et, enfin, une tentative de réponse à votre question actuelle : quand et où ? rep movsb
pourrait avoir du sens.
En partie, il s'agit d'une appel à partager les résultats - si vous pouvez exécuter Tinymembench et partagez les résultats ainsi que les détails de votre configuration CPU et RAM, ce serait formidable. Surtout si vous avez une configuration à 4 canaux, une boîte Ivy Bridge, une boîte de serveur, etc.
Historique et avis officiel
L'histoire des performances des instructions de copie rapide de chaînes de caractères a été un peu une affaire de marches d'escalier - c'est-à-dire des périodes de stagnation des performances alternant avec des mises à jour importantes qui les ont alignées ou même plus rapides que les approches concurrentes. Par exemple, les performances ont fait un bond dans Nehalem (en ciblant principalement les frais de démarrage) et à nouveau dans Ivy Bridge (en ciblant principalement le débit total pour les grandes copies). Vous pouvez trouver des informations vieilles de dix ans sur les difficultés de la mise en œuvre du rep movs
instructions d'un ingénieur d'Intel dans ce fil .
Par exemple, dans les guides qui ont précédé l'introduction de l'Ivy Bridge, le modèle typique de l'Ivy Bridge était le suivant conseils est de les éviter ou de les utiliser très soigneusement 1 .
Le guide actuel (enfin, juin 2016) contient une série de conseils confus et quelque peu incohérents, tels que 2 :
La variante spécifique de l'implémentation est choisie au moment de l'exécution en fonction de la disposition des données, de l'alignement et de la valeur du compteur (ECX). Pour Par exemple, MOVSB/STOSB avec le préfixe REP doit être utilisé avec une valeur de inférieure ou égale à trois pour de meilleures performances.
Donc pour les copies de 3 octets ou moins ? Vous n'avez pas besoin d'un rep
en premier lieu, puisqu'avec une latence de démarrage annoncée de ~9 cycles, vous êtes presque certainement mieux loti avec un simple DWORD ou QWORD. mov
avec un peu de manipulation pour masquer les octets inutilisés (ou peut-être avec 2 octets explicites, mot mov
si vous savez que la taille est exactement de trois).
Ils poursuivent :
Les instructions String MOVE/STORE ont plusieurs granularités de données. Pour déplacement efficace des données, il est préférable d'utiliser des granularités de données plus grandes. Cela signifie qu'une meilleure efficacité peut être obtenue en décomposant une instruction de type valeur de compteur arbitraire en un certain nombre de doubles mots et d'octets uniques avec une valeur de comptage inférieure ou égale à 3.
Cela semble certainement faux sur le matériel actuel avec ERMSB où rep movsb
est au moins aussi rapide, voire plus rapide, que le programme movd
o movq
variantes pour les grandes copies.
D'une manière générale, cette section (3.7.5) du guide actuel contient un mélange de conseils raisonnables et fortement obsolètes. Ceci est commun à tous les manuels Intel, puisqu'ils sont mis à jour de manière incrémentale pour chaque architecture (et prétendent couvrir près de vingt ans d'architectures, même dans le manuel actuel), et les anciennes sections ne sont souvent pas mises à jour pour remplacer ou rendre conditionnels les conseils qui ne s'appliquent pas à l'architecture actuelle.
Ils couvrent ensuite explicitement l'ERMSB dans la section 3.7.6.
Je ne vais pas passer en revue les autres conseils de manière exhaustive, mais je vais résumer les bonnes parties dans le "pourquoi l'utiliser" ci-dessous.
D'autres affirmations importantes du guide sont celles concernant Haswell, rep movsb
a été amélioré pour utiliser des opérations de 256 bits en interne.
Considérations techniques
Il ne s'agit là que d'un résumé rapide des avantages et des inconvénients sous-jacents que l'on peut trouver dans le secteur de la santé. rep
instructions ont d'un plan de mise en oeuvre .
Avantages pour rep movs
-
Lorsqu'un rep
movs est émise, le CPU connaît qu'un bloc entier d'une taille connue doit être transféré. Cela peut l'aider à optimiser l'opération d'une manière qu'il ne peut pas faire avec des instructions discrètes, par exemple :
- Éviter la demande RFO lorsqu'il sait que la ligne de cache entière sera écrasée.
- Émettre des requêtes prefetch immédiatement et exactement. Le préfixe matériel fait un bon travail pour détecter
memcpy
mais il faut encore quelques lectures pour qu'elle se mette en marche et elle "sur-préfetch" de nombreuses lignes de cache au-delà de la fin de la région copiée. rep movsb
connaît exactement la taille de la région et peut préfixer exactement.
-
Apparemment, il n'y a pas de garantie de commande parmi les magasins de l'Union européenne. 3 un seul rep movs
ce qui peut contribuer à simplifier le trafic de cohérence et simplement d'autres aspects du déplacement du bloc, par rapport à une simple mov
qui doivent obéir à un ordonnancement assez strict de la mémoire. 4 .
-
En principe, le rep movs
pourrait profiter de diverses astuces architecturales qui ne sont pas exposées dans l'ISA. Par exemple, les architectures peuvent avoir des chemins de données internes plus larges que ceux que l'ISA expose. 5 y rep movs
pourrait l'utiliser en interne.
Inconvénients
-
rep movsb
doit mettre en œuvre une sémantique spécifique qui peut être plus forte que l'exigence logicielle sous-jacente. En particulier, memcpy
interdit les régions qui se chevauchent, et peut donc ignorer cette possibilité, mais rep movsb
les autorise et doit produire le résultat escompté. Dans les implémentations actuelles, cela affecte surtout le surcoût de démarrage, mais probablement pas le débit des gros blocs. De même, rep movsb
doit prendre en charge les copies granulaires d'octets, même si vous l'utilisez en réalité pour copier de grands blocs qui sont un multiple d'une grande puissance de 2.
-
Le logiciel peut disposer d'informations sur l'alignement, la taille de la copie et le crénelage éventuel qui ne peuvent pas être communiquées au matériel si l'on utilise la fonction rep movsb
. Les compilateurs peuvent souvent déterminer l'alignement des blocs de mémoire 6 et peut ainsi éviter une grande partie du travail de démarrage qui rep movs
doit faire sur chaque l'invocation.
Résultats des tests
Voici les résultats de tests pour de nombreuses méthodes de copie différentes de tinymembench
sur mon i7-6700HQ à 2,6 GHz (dommage que j'aie le même processeur et que nous n'ayons pas un nouveau point de données...) :
C copy backwards : 8284.8 MB/s (0.3%)
C copy backwards (32 byte blocks) : 8273.9 MB/s (0.4%)
C copy backwards (64 byte blocks) : 8321.9 MB/s (0.8%)
C copy : 8863.1 MB/s (0.3%)
C copy prefetched (32 bytes step) : 8900.8 MB/s (0.3%)
C copy prefetched (64 bytes step) : 8817.5 MB/s (0.5%)
C 2-pass copy : 6492.3 MB/s (0.3%)
C 2-pass copy prefetched (32 bytes step) : 6516.0 MB/s (2.4%)
C 2-pass copy prefetched (64 bytes step) : 6520.5 MB/s (1.2%)
---
standard memcpy : 12169.8 MB/s (3.4%)
standard memset : 23479.9 MB/s (4.2%)
---
MOVSB copy : 10197.7 MB/s (1.6%)
MOVSD copy : 10177.6 MB/s (1.6%)
SSE2 copy : 8973.3 MB/s (2.5%)
SSE2 nontemporal copy : 12924.0 MB/s (1.7%)
SSE2 copy prefetched (32 bytes step) : 9014.2 MB/s (2.7%)
SSE2 copy prefetched (64 bytes step) : 8964.5 MB/s (2.3%)
SSE2 nontemporal copy prefetched (32 bytes step) : 11777.2 MB/s (5.6%)
SSE2 nontemporal copy prefetched (64 bytes step) : 11826.8 MB/s (3.2%)
SSE2 2-pass copy : 7529.5 MB/s (1.8%)
SSE2 2-pass copy prefetched (32 bytes step) : 7122.5 MB/s (1.0%)
SSE2 2-pass copy prefetched (64 bytes step) : 7214.9 MB/s (1.4%)
SSE2 2-pass nontemporal copy : 4987.0 MB/s
Quelques éléments clés à retenir :
- El
rep movs
sont plus rapides que toutes les autres méthodes qui ne sont pas "non-temporelles". 7 et beaucoup plus rapide que les approches "C" qui copient 8 octets à la fois.
- Les méthodes "non temporelles" sont plus rapides, jusqu'à environ 26 %, que les méthodes "temporelles".
rep movs
mais il s'agit d'un écart beaucoup plus faible que celui que vous avez indiqué (26 Go/s contre 15 Go/s = ~73 %).
- Si vous n'utilisez pas de magasins non temporels, l'utilisation de copies de 8 octets à partir de C est à peu près aussi bonne que les chargements/stocks SSE de 128 bits. En effet, une bonne boucle de copie peut générer une pression mémoire suffisante pour saturer la bande passante (par exemple, 2,6 GHz * 1 magasin/cycle * 8 octets = 26 Go/s pour les magasins).
- Il n'y a pas d'algorithmes 256 bits explicites dans tinymembench (à l'exception probablement de l'algorithme "standard").
memcpy
) mais cela n'a probablement pas d'importance en raison de la note ci-dessus.
- L'augmentation du débit des approches de stockage non temporelles par rapport aux approches temporelles est d'environ 1,45x, ce qui est très proche du 1,5x auquel on pourrait s'attendre si NT élimine 1 transfert sur 3 (c'est-à-dire, 1 lecture, 1 écriture pour NT contre 2 lectures, 1 écriture). Le site
rep movs
les approches se situent au milieu.
- La combinaison d'une latence mémoire assez faible et d'une modeste bande passante à deux canaux signifie que cette puce particulière est capable de saturer sa bande passante mémoire à partir d'un seul thread, ce qui change radicalement le comportement.
-
rep movsd
semble utiliser la même magie que rep movsb
sur cette puce. C'est intéressant car l'ERMSB ne cible explicitement que movsb
et des tests antérieurs sur des arcs plus anciens avec ERMSB montrent movsb
qui fonctionne beaucoup plus rapidement que movsd
. Il s'agit là d'une question purement théorique puisque movsb
est plus général que movsd
de toute façon.
Haswell
En regardant le Résultats Haswell aimablement fourni par iwillnotexist dans les commentaires, nous constatons les mêmes tendances générales (résultats les plus pertinents extraits) :
C copy : 6777.8 MB/s (0.4%)
standard memcpy : 10487.3 MB/s (0.5%)
MOVSB copy : 9393.9 MB/s (0.2%)
MOVSD copy : 9155.0 MB/s (1.6%)
SSE2 copy : 6780.5 MB/s (0.4%)
SSE2 nontemporal copy : 10688.2 MB/s (0.3%)
El rep movsb
est toujours plus lente que l'approche non temporelle. memcpy
mais seulement d'environ 14 % ici (contre ~26 % dans le test Skylake). L'avantage des techniques NT par rapport à leurs cousines temporelles est maintenant de ~57%, même un peu plus que l'avantage théorique de la réduction de la bande passante.
Quand devez-vous utiliser rep movs
?
Enfin, je réponds à votre question : quand ou pourquoi l'utiliser ? Il s'inspire de ce qui précède et introduit quelques nouvelles idées. Malheureusement, il n'y a pas de réponse simple : vous devrez arbitrer entre différents facteurs, dont certains que vous ne pouvez probablement même pas connaître exactement, comme les développements futurs.
Il convient de noter que l'alternative à rep movsb
peut être la libc optimisée memcpy
(y compris les copies inlined par le compilateur), ou bien il peut s'agir d'une version de memcpy
version. Certains des avantages ci-dessous ne s'appliquent que par rapport à l'une ou l'autre de ces alternatives (par exemple, la "simplicité" est utile par rapport à une version roulée à la main, mais pas par rapport à une version intégrée). memcpy
), mais certaines s'appliquent aux deux.
Restrictions sur les instructions disponibles
Dans certains environnements, il existe une restriction sur certaines instructions ou sur l'utilisation de certains registres. Par exemple, dans le noyau Linux, l'utilisation des registres SSE/AVX ou FP est généralement interdite. Par conséquent, la plupart des programmes optimisés de memcpy
ne peuvent pas être utilisées, car elles reposent sur les registres SSE ou AVX, et une simple version 64 bits de l'interface utilisateur. mov
-La copie basée sur les données est utilisée sur x86. Pour ces plateformes, l'utilisation de rep movsb
permet de bénéficier de la plupart des performances d'un memcpy
sans briser la restriction sur le code SIMD.
Un exemple plus général pourrait être le code qui doit cibler plusieurs générations de matériel, et qui n'utilise pas de répartition spécifique au matériel (par exemple, l'utilisation de cpuid
). Dans ce cas, vous pourriez être contraint d'utiliser uniquement des jeux d'instructions plus anciens, ce qui exclut tout AVX, etc. rep movsb
pourrait être une bonne approche ici puisqu'elle permet un accès "caché" à des chargements et des stockages plus larges sans utiliser de nouvelles instructions. Si vous ciblez du matériel pré-ERMSB, vous devrez voir si les instructions suivantes sont possibles rep movsb
les performances y sont acceptables, cependant...
Préparer l'avenir
Un aspect intéressant de rep movsb
c'est qu'elle le peut, en théorie profiter des améliorations architecturales sur les architectures futures, sans changement de source, ce que les déplacements explicites ne peuvent pas faire. Par exemple, lorsque les chemins de données de 256 bits ont été introduits, rep movsb
a pu en tirer parti (comme le prétendait Intel) sans qu'il soit nécessaire de modifier le logiciel. Les logiciels utilisant des déplacements de 128 bits (ce qui était optimal avant Haswell) devaient être modifiés et recompilés.
Il s'agit donc à la fois d'un avantage pour la maintenance du logiciel (pas besoin de changer la source) et d'un avantage pour les binaires existants (pas besoin de déployer de nouveaux binaires pour profiter de l'amélioration).
L'importance de cet aspect dépend de votre modèle de maintenance (par exemple, la fréquence de déploiement des nouveaux binaires dans la pratique) et d'un jugement très difficile à porter sur la rapidité probable de ces instructions à l'avenir. Au moins, Intel guide les utilisations dans cette direction, en s'engageant à au moins raisonnable performance à l'avenir ( 15.3.3.6 ):
REP MOVSB et REP STOSB continueront à être raisonnablement performants sur les processeurs futurs.
Chevauchement avec des travaux ultérieurs
Cet avantage n'apparaîtra pas dans un simple memcpy
Il s'agit bien sûr d'un point de référence qui, par définition, n'a pas de travail ultérieur à superposer, de sorte que l'ampleur de l'avantage devrait être soigneusement mesurée dans un scénario réel. Pour tirer le maximum d'avantages, il faudrait peut-être réorganiser le code entourant la fonction memcpy
.
Cet avantage est souligné par Intel dans son manuel d'optimisation (section 11.16.3.4) et dans ses mots :
Lorsque l'on sait que le comptage est d'au moins mille octets ou plus, l'utilisation de l'utilisation du REP MOVSB/STOSB amélioré peut fournir un autre avantage pour amortir le coût du code non-consommateur. L'heuristique peut être comprise en utilisant une valeur de Cnt = 4096 et memset() comme exemple :
- Une implémentation SIMD 256 bits de memset() devra émettre/exécuter retirer 128 instances d'une opération de stockage de 32 octets avec VMOVDQA, avant que que les séquences d'instructions non consommatrices puissent se rendre à la retraite.
- Une instance de REP STOSB amélioré avec ECX= 4096 est décodée en tant qu'un long flux de micro-opérations fourni par le matériel, mais se retire en tant qu'une seule instruction. Il y a beaucoup d'opérations store_data qui doivent se terminer avant que le résultat de memset() puisse être consommé. Parce que l'achèvement l'achèvement de l'opération de stockage des données est découplé de la retraite de l'ordre du programme. une partie substantielle du flux de code non-consommateur peut être traitée à travers l'émission/exécution et le retrait, essentiellement sans coût si la séquence de si la séquence non consommatrice n'entre pas en concurrence avec les ressources du tampon de stockage.
Donc Intel dit qu'après tous les quelques uops le code après rep movsb
a été émis, mais alors que de nombreux magasins sont encore en vol et que la rep movsb
dans son ensemble n'a pas encore été retiré, les uops des instructions suivantes peuvent progresser davantage à travers la machinerie hors-ordre que si ce code venait après une boucle de copie.
Les uops d'une boucle explicite de chargement et de stockage doivent tous être retirés séparément dans l'ordre du programme. Cela doit se produire pour faire de la place dans le ROB pour les uops suivants.
Il ne semble pas y avoir beaucoup d'informations détaillées sur la façon dont une instruction microcodée très longue comme rep movsb
le travail, exactement. Nous ne savons pas exactement comment les branches de microcodes demandent un flux différent d'uops au séquenceur de microcodes, ou comment les uops se retirent. Si les uops individuels n'ont pas à se retirer séparément, peut-être que l'instruction entière ne prend qu'un seul slot dans le ROB ?
Lorsque le frontal qui alimente la machine OoO voit une rep movsb
dans le cache des uop, il active le Microcode Sequencer ROM (MS-ROM) pour envoyer des uop de microcode dans la file d'attente qui alimente l'étape d'émission/renommage. Il n'est probablement pas possible pour d'autres uop de se mêler à cette file et d'émettre/exécuter. 8 tandis que rep movsb
est toujours en cours d'émission, mais les instructions suivantes peuvent être récupérées/décodées et émises juste après la dernière instruction rep movsb
uop fait, alors qu'une partie de la copie n'a pas encore été exécutée. Ceci n'est utile que si au moins une partie de votre code ultérieur ne dépend pas du résultat de la fonction memcpy
(ce qui n'est pas inhabituel).
Or, la taille de cet avantage est limitée : au maximum, vous pouvez exécuter N instructions (uops en fait) au-delà de la lenteur de l'ordinateur. rep movsb
à laquelle vous décrocherez, où N est l'instruction Taille du ROB . Avec des tailles de ROB actuelles de ~200 (192 sur Haswell, 224 sur Skylake), cela représente un avantage maximal de ~200 cycles de travail gratuit pour le code suivant avec un IPC de 1. En 200 cycles, vous pouvez copier environ 800 octets à 10 Go/s, donc pour des copies de cette taille, vous pouvez obtenir un travail gratuit proche du coût de la copie (rendant en quelque sorte la copie gratuite).
Cependant, à mesure que la taille des copies augmente, l'importance relative de ce facteur diminue rapidement (par exemple, si vous copiez plutôt 80 Ko, le travail gratuit ne représente que 1 % du coût de la copie). Cela reste néanmoins intéressant pour les copies de taille modeste.
Les boucles de copie ne bloquent pas non plus totalement l'exécution des instructions suivantes. Intel ne donne pas de détails sur la taille de l'avantage, ni sur le type de copies ou de code environnant qui en bénéficie le plus. (Destination ou source chaude ou froide, code après haute ILP ou basse ILP à latence élevée).
Code Taille
La taille du code exécuté (quelques octets) est microscopique par rapport à un code optimisé typique. memcpy
routine. Si les performances sont limitées par les manques dans le i-cache (y compris le uop cache), la réduction de la taille du code peut être bénéfique.
Là encore, nous pouvons délimiter l'ampleur de cet avantage en fonction de la taille de la copie. Je ne le calculerai pas numériquement, mais l'intuition est que la réduction de la taille du code dynamique de B octets permet d'économiser au maximum C * B
cache-miss, pour une certaine constante C. Chaque appelez à memcpy
subit le coût (ou le bénéfice) de l'absence de cache une fois, mais l'avantage d'un débit plus élevé s'échelonne avec le nombre d'octets copiés. Ainsi, pour les transferts importants, le débit plus élevé dominera les effets du cache.
Encore une fois, ce n'est pas quelque chose qui apparaîtra dans un benchmark ordinaire, où la boucle entière tiendra sans doute dans le cache uop. Vous aurez besoin d'un test réel, in-place, pour évaluer cet effet.
Optimisation spécifique à l'architecture
Vous l'avez signalé sur votre matériel, rep movsb
était considérablement plus lente que la plateforme memcpy
. Toutefois, même dans ce cas, des rapports font état du résultat inverse sur du matériel antérieur (comme Ivy Bridge).
C'est tout à fait plausible, puisqu'il semble que les opérations de déplacement de la chaîne de caractères soient améliorées périodiquement - mais pas à chaque génération, de sorte qu'il est possible qu'il soit plus rapide ou au moins à égalité (auquel cas il peut gagner sur la base d'autres avantages) sur les architectures où il a été mis à jour, pour ensuite prendre du retard sur le matériel suivant.
Citation : Andy Glew, qui devrait savoir une chose ou deux à ce sujet après avoir mis en œuvre ceux-ci sur le P6 :
la grande faiblesse de faire des chaînes rapides en microcode était [...] le microcode se déréglait avec chaque génération, devenant de plus en plus lent jusqu'à ce que quelqu'un se décide à le réparer. Tout comme une bibliothèque que les hommes d'une bibliothèque se désaccordait. Je suppose qu'il est possible que l'une des opportunités manquées a été d'utiliser des chargements et des stockages de 128 bits quand ils quand ils sont devenus disponibles, et ainsi de suite.
Dans ce cas, on peut considérer qu'il s'agit d'une optimisation "spécifique à la plate-forme" de plus à appliquer dans le cadre de l'approche typique du "tout-trick-dans-le-livre". memcpy
que l'on trouve dans les bibliothèques standard et les compilateurs JIT : mais seulement pour une utilisation sur les architectures où c'est mieux. Pour les éléments compilés en JIT ou en AOT, c'est facile, mais pour les binaires compilés de manière statique, cela nécessite une distribution spécifique à la plate-forme, mais qui existe souvent déjà (parfois implémentée au moment de l'édition du lien), ou l'option de gestion de l'architecture. mtune
peut être utilisé pour prendre une décision statique.
Simplicité
Même sur Skylake, où il semble qu'il ait pris du retard par rapport aux techniques non temporelles les plus rapides, il reste plus rapide que la plupart des approches et est très simple . Cela signifie moins de temps de validation, moins de bugs mystérieux, moins de temps de réglage et de mise à jour d'un monstre. memcpy
(ou, à l'inverse, moins de dépendance vis-à-vis des caprices des implémenteurs de la bibliothèque standard si vous comptez sur celle-ci).
Plateformes à latence limitée
Algorithmes de limitation du débit mémoire 9 peut en fait fonctionner dans deux régimes généraux principaux : la bande passante de la DRAM ou la concurrence/latence.
Le premier mode est celui que vous connaissez probablement : le sous-système DRAM a une certaine largeur de bande théorique que vous pouvez calculer assez facilement en fonction du nombre de canaux, du débit/largeur de données et de la fréquence. Par exemple, mon système DDR4-2133 avec 2 canaux a une bande passante maximale de 2.133 * 8 * 2 = 34.1 GB/s, soit la même chose que rapporté sur ARK .
Vous ne supporterez pas plus que ce taux à partir de la DRAM (et généralement un peu moins en raison de diverses inefficacités) ajouté à tous les cœurs sur le socket (c'est-à-dire qu'il s'agit d'une limite globale pour les systèmes à un seul socket).
L'autre limite est imposée par le nombre de demandes simultanées qu'un cœur peut effectivement adresser au sous-système de mémoire. Imaginez qu'un cœur ne puisse avoir qu'une seule requête en cours à la fois, pour une ligne de cache de 64 octets - lorsque la requête est terminée, vous pouvez en émettre une autre. Supposons également une latence mémoire très rapide de 50ns. Alors, malgré la large bande passante DRAM de 34,1 Go/s, vous n'obtiendriez en fait que 64 octets / 50 ns = 1,28 Go/s, soit moins de 4 % de la bande passante maximale.
En pratique, les cœurs peuvent émettre plus d'une requête à la fois, mais pas un nombre illimité. Il est généralement entendu qu'il n'y a que 10 tampons de remplissage de ligne par cœur entre L1 et le reste de la hiérarchie mémoire, et peut-être 16 ou plus tampons de remplissage entre L2 et DRAM. Le prefetching est en concurrence pour les mêmes ressources, mais il permet au moins de réduire la latence effective. Pour plus de détails, consultez l'un des articles suivants Dr. Bandwidth a écrit sur le sujet principalement sur les forums Intel.
Encore, le plus Les processeurs récents sont limités par este et non la bande passante de la RAM. En général, ils atteignent 12 à 20 Go/s par cœur, alors que la bande passante de la RAM peut atteindre 50+ Go/s (sur un système à 4 canaux). Seuls certains cœurs "clients" récents à 2 canaux, qui semblent avoir un meilleur uncore, peut-être plus de tampons de ligne, peuvent atteindre la limite de DRAM sur un seul cœur, et nos puces Skylake semblent en faire partie.
Bien sûr, il y a une raison pour laquelle Intel conçoit des systèmes avec une bande passante DRAM de 50 Go/s, alors qu'ils ne peuvent supporter qu'une bande passante < 20 Go/s par cœur en raison des limites de concurrence : la première limite s'applique à l'ensemble du socket et la seconde à chaque cœur. Ainsi, chaque cœur d'un système à 8 cœurs peut envoyer des requêtes d'une valeur de 20 Go/s, après quoi il sera à nouveau limité par la DRAM.
Pourquoi je continue à parler de ça ? Parce que le meilleur memcpy
La mise en œuvre dépend souvent du régime dans lequel vous opérez. Une fois que vous êtes limité par la bande passante de la DRAM (comme nos puces le sont apparemment, mais la plupart ne le sont pas sur un seul cœur), l'utilisation d'écritures non temporelles devient très importante car elle permet d'éviter la lecture pour la propriété qui gaspille normalement 1/3 de votre bande passante. Vous le voyez exactement dans les résultats des tests ci-dessus : les implémentations de memcpy qui Ne le fais pas. utilisent les magasins NT perdent 1/3 de leur bande passante.
En revanche, si la concurrence est limitée, la situation s'égalise et parfois s'inverse. Vous avez de la bande passante DRAM à revendre, donc les magasins NT n'aident pas et ils peuvent même nuire puisqu'ils peuvent augmenter la latence puisque le temps de transfert pour le tampon de ligne peut être plus long qu'un scénario où la pré-extraction amène la ligne RFO dans LLC (ou même L2) et ensuite le magasin se termine dans LLC pour une latence effective plus faible. Enfin, servidor Les uncores ont tendance à avoir des magasins NT beaucoup plus lents que ceux des clients (et une bande passante élevée), ce qui accentue cet effet.
Ainsi, sur d'autres plates-formes, vous pourriez trouver que les magasins NT sont moins utiles (au moins lorsque vous vous souciez de la performance d'un seul thread) et peut-être que rep movsb
gagne où (si elle obtient le meilleur des deux mondes).
Vraiment, ce dernier point est un appel pour la plupart des tests. Je sais que les magasins NT perdent leur avantage apparent pour les tests monofilaires sur la plupart des archs (y compris les archs serveurs actuels), mais je ne sais pas comment rep movsb
sera relativement performant...
Références
Autres bonnes sources d'information non intégrées dans ce qui précède.
enquête comp.arch de rep movsb
contre les alternatives. Beaucoup de bonnes notes sur la prédiction des branches, et une implémentation de l'approche que j'ai souvent suggérée pour les petits blocs : utiliser des premières et/ou dernières lectures/écritures qui se chevauchent plutôt que d'essayer d'écrire seulement le nombre exact d'octets requis (par exemple, implémenter toutes les copies de 9 à 16 octets comme deux copies de 8 octets qui pourraient se chevaucher jusqu'à 7 octets).
1 L'intention est probablement de la limiter aux cas où, par exemple, la taille du code est très importante.
2 Voir Section 3.7.5 : Préfixe REP et mouvement des données.
3 Il est important de noter que cela ne s'applique qu'aux différents magasins de l'instruction unique elle-même : une fois terminé, le bloc de magasins apparaît toujours ordonné par rapport aux magasins précédents et suivants. Ainsi, le code peut voir les stockages de l'instruction rep movs
hors d'usage les uns par rapport aux autres mais pas en ce qui concerne les magasins antérieurs ou postérieurs (et c'est cette dernière garantie dont vous avez généralement besoin). Ce ne sera un problème que si vous utilisez la fin de la destination de la copie comme un indicateur de synchronisation, au lieu d'un magasin séparé.
4 Notez que les magasins discrets non temporels évitent également la plupart des exigences d'ordonnancement, bien qu'en pratique rep movs
a encore plus de liberté car il existe encore quelques contraintes de commande sur les magasins WC/NT.
5 C'était courant à la fin de l'ère 32 bits, lorsque de nombreuses puces disposaient de chemins de données 64 bits (par exemple, pour prendre en charge les FPU qui supportaient le 64 bits). double
type). Aujourd'hui, les puces "neutrées" telles que les marques Pentium ou Celeron ont AVX désactivé, mais vraisemblablement rep movs
Le microcode peut toujours utiliser des chargements/stockages de 256b.
6 Par exemple, en raison des règles d'alignement du langage, des attributs ou opérateurs d'alignement, des règles d'aliasing ou d'autres informations déterminées au moment de la compilation. Dans le cas de l'alignement, même si l'alignement exact ne peut être déterminé, ils peuvent au moins être en mesure d'extraire les contrôles d'alignement des boucles ou d'éliminer les contrôles redondants.
7 Je pars du principe que "standard" memcpy
choisit une approche non temporelle, ce qui est très probable pour cette taille de tampon.
8 Ce n'est pas forcément évident, car il se pourrait que le flux d'uop généré par la commande rep movsb
monopolise simplement la répartition et alors cela ressemblerait beaucoup à l'explicite mov
le cas. Il semble cependant que cela ne fonctionne pas de cette manière - les uops des instructions suivantes peuvent se mélanger avec les uops de l'instruction microcodée. rep movsb
.
9 C'est-à-dire ceux qui peuvent émettre un grand nombre de requêtes mémoire indépendantes et donc saturer la bande passante DRAM-cœur disponible, dont memcpy
serait un exemple (par opposition aux charges purement liées à la latence, comme la recherche de pointeurs).
0 votes
"Que puis-je faire pour l'améliorer?" ... fondamentalement rien. L'implémentation
memcpy
dans la version actuelle du compilateur est très probablement aussi proche de la solution optimale que vous pouvez obtenir avec une fonction générique. Si vous avez un cas spécial comme déplacer toujours exactement 15 octets/ect, alors peut-être qu'une solution asm personnalisée pourrait battre le compilateur gcc, mais si votre source C est assez explicite sur ce qui se passe (donnant de bons indices au compilateur sur l'alignement, la longueur, etc), le compilateur produira très probablement un code machine optimal même pour ces cas spécialisés. Vous pouvez essayer d'améliorer d'abord la sortie du compilateur.7 votes
@KerrekSB Savez-vous ce qu'est le movsb rep amélioré ?
3 votes
@Ped7g, je n'attends pas que ce soit mieux que
memcpy
. Je m'attends à ce que ce soit aussi bon quememcpy
. J'ai utilisé gdb pour parcourirmemcpy
et j'ai vu qu'il entre dans une boucle principale avecrep movsb
. C'est donc apparemment ce quememcpy
utilise de toute façon (dans certains cas).2 votes
Changer l'ordre des tests. Quels résultats obtenez-vous ensuite?
2 votes
@Art, j'obtiens le même résultat (26 Go/s pour memcpy et 15 Go/s pour __movsb).
0 votes
D'accord. En cas de doute, suspectez le benchmark. Mais cela ne semble pas être le problème ici. Pour ce que ça vaut, c'est plus rapide sur une machine Ivy Bridge à laquelle j'avais accès (à la fois lors de la première et de la deuxième exécution).
0 votes
@Art, c'est intéressant! Je me demande pourquoi c'est sur votre système IVB. Oui, les tests de performance sont pénibles. J'ai récemment répondu à une question que j'ai dû éditer plusieurs fois en raison de problèmes de tests de performances auxquels je ne m'attendais pas.
0 votes
@Art peut-être que
enhanced rep movsb
n'est pas si amélioré sur Skylake (mon système) ? Je ne comprends toujours pas pourquoi tu as dû changer l'ordre.0 votes
@Zboson L'ordre ne importait pas pour moi non plus. Le commentaire "Changer l'ordre" était avant que je trouve une machine avec le bon CPU. Il est aussi 50% plus rapide, ce qui est assez significatif. D'autre part, sur une autre machine avec un CPU plus récent, les performances sont inversées.
0 votes
@Art, quelle fonction était 50% plus rapide et sur quelle machine ?
1 votes
@Zboson la fonction movsb était 50% plus rapide sur une machine Ivy Bridge.
0 votes
@Zboson : Non, je n'ai pas entendu parler de ça, désolé. Le terme est-il défini dans le manuel d'instruction Intel ?
3 votes
@KerrekSB, oui, c'est dans la section "3.7.6 Opération améliorée REP MOVSB et STOSB (ERMSB)"
0 votes
Intéressant. Avez-vous vérifié avec cpuid que la fonctionnalité est disponible sur votre CPU?
3 votes
Le manuel d'optimisation suggère que ERMSB est meilleur pour fournir une taille de code réduite et une meilleure efficacité que le traditionnel REP-MOV/STO, mais "implémenter memcpy en utilisant ERMSB pourrait ne pas atteindre le même niveau de débit que l'utilisation d'alternatives AVX de 256 bits ou 128 bits, selon la longueur et les facteurs d'alignement." La façon dont je comprends cela est qu'il est amélioré pour les situations où vous auriez précédemment utilisé des instructions rep, mais il ne vise pas à rivaliser avec les alternatives modernes à haut débit.
0 votes
@KerrekSB, non. Je suppose que les processeurs depuis Ivy Bridge l'ont.
less /proc/cpuinfo | grep erms
montre erms.0 votes
@Zboson: Oui, même chose, c'est assez bien.
0 votes
@KerrekSB, ouais, j'ai lu cette déclaration mais j'étais confus par cela. Je me base sur le commentaire "rep movsb est significativement plus rapide que movntdqa lors du streaming vers la mémoire sur Ivybridge et Haswell (mais sachez qu'avant Ivybridge c'est lent!)" (voir la mise à jour à la fin de ma question).
1 votes
Comment serait-il de parcourir le code machine dans un débogueur et de vérifier si votre memcpy utilise effectivement movntdqa? Il semble plausible qu'il utilise des instructions SSE ou AVX à la place. J'ai le sentiment que ERMSB est censé être meilleur que certains éléments, pas meilleur que tout.
0 votes
J'ai utilisé
gdb
pour étudiermemcpy
. Pour une taille définie à l'exécution, il utilisait des magasins non temporels et un préchargement. Pour la même taille (1 Go) définie à la compilation, il utilisaitrep movsb
. Je n'ai regardé qu'une fois donc il est possible que j'ai mal interprété quelque chose. Ma propre implémentation utilisantmovntdqa
se comporte à peu près aussi bien quememcpy
.1 votes
@Zboson: Vous avez besoin d'un meilleur micro-benchmark/test de timing. Votre source et votre destination sont tous les deux alignés sur des vecteurs AVX, ce qui affectera la manière dont le compilateur implémentera la fonction memcpy(). J'ai effectué des tests similaires en utilisant des tuples source-cible-longueur pseudo-aléatoires prégénérés, avec différentes situations d'alignement testées séparément, pour mieux imiter des cas d'utilisation réels. Mais, mon code du monde réel copie généralement des données froides, et le timing du comportement du cache froid est difficile. Peut-être envisager de chronométrer une tâche réelle lourde en memcpy()/memmove()?
0 votes
@NominalAnimal, c'est un point intéressant. Vous voulez dire que l'ERMSB est utile dans des situations moins idéales, par exemple lorsque la destination et la source ne sont pas alignées. Je pensais que l'alignement était essentiel pour l'ERMSB? Dans tous les cas, si vous pouvez démontrer où l'ERMSB est utile, ce serait une bonne réponse. Montrez-moi un meilleur microbenchmark/test de timing.
2 votes
@NominalAnimal Le Manuel d'Optimisation d'Intel, Tableau 3-4 affirme que lorsque à la fois la source et la destination sont alignées sur au moins 16 octets et que la taille du transfert est de 128 à 4096 octets, ERMSB répond ou dépasse le
memcpy()
basé sur AVX d'Intel. Bien que personne ne sache ce qu'est cememcpy()
, on peut raisonnablement supposer qu'Intel saurait comment obtenir plus de 50% de la bande passante maximale sur leur propre puce.0 votes
@IwillnotexistIdonotexist, vous n'avez pas besoin de comparer à
memcpy
. Vous pourriez comparer ERMSB à une solution SSE/AVX ou mieux à une solution avec des opérations de stockage non temporelles. C'est ce que je ferais dans ce cas: utiliser des opérations de stockage non temporelles. Mais ce commentaire et le commentaire qui a suivi ont dit que même dans le cas de 1 Go, ERMSB devrait l'emporter. Les opérations de stockage non temporelles ne devraient-elles pas empêcher les prélecteurs de lire la destination? Je pensais que c'était là l'intérêt de les utiliser.5 votes
@Zboson Mon
memcpy()
de glibc utilise les AVX NT stores. Et à la fois les NT stores et les ERMSB se comportent de manière write-combining, et par conséquent ne devraient pas nécessiter de RFO's. Néanmoins, mes tests de performance sur ma propre machine montrent que monmemcpy()
et mon ERMSB atteignent tous deux leur limite à 2/3 de la bande passante totale, comme votrememcpy()
(mais pas votre ERMSB) l'a fait. Par conséquent, il y a clairement une transaction de bus supplémentaire quelque part, et cela ressemble beaucoup à un RFO.0 votes
@JeNexisteraipasTaimeNexistepas votre observation 2/3 est très intéressante. Je pense que je peux faire mieux que 2/3 en utilisant deux fils. Je ne suis pas sûr pourquoi mon ERMSB sur Skylake se comporte moins bien que votre ERMSB sur Haswell.
0 votes
@IwillnotexistIdonotexist, avez-vous vu un quelconque bénéfice pour plus de 2 threads? Je n'ai jamais regardé les compteurs de performance auparavant. C'est une faiblesse que je dois corriger. Quels outils utilisez-vous pour cela? Agner Fog a un outil pour ça mais c'était un peu compliqué. Je devrais y jeter un oeil à nouveau. Et que pensez-vous de
perf
? Si vous répondez à la question, veuillez partager les détails.2 votes
@Zboson À 2 threads, c'est environ 21Go/s, à 4+ ça atteint la saturation à 23Go/s. J'examine les compteurs de performance en utilisant un logiciel fait maison que j'ai écrit:
libpfc
. C'est peu fiable, beaucoup plus limité queocperf.py
, uniquement connu pour fonctionner sur ma propre machine, ne fonctionne correctement que pour les codes monoprocesseurs, mais parce que je peux facilement (re)programmer les compteurs et accéder aux timings de l'intérieur du programme, et que je peux bien encadrer le code à vérifier, cela répond à mes besoins. Un jour, j'aurai le temps de résoudre ses nombreux problèmes.1 votes
En cas où quelqu'un se soucie voici une solution d'assemblage en ligne plus simple
void __movsb(void* dst, const void* src, size_t size) { __asm__ __volatile__("rep movsb" : "+D"(dst), "+S"(src), "+c"(size) : : "memory"); }
que j'ai trouvée ici hero.handmade.network/forums/code-discussion/t/…0 votes
Il semble qu'une réponse raisonnable pourrait être que c'était plus rapide, ou du moins aussi rapide en IVB (selon certains résultats référencés ici), mais que le micro-code associé ne reçoit pas nécessairement toute l'attention à chaque génération, de sorte qu'il devient plus lent que le code explicite, qui utilise toujours la fonctionnalité de base du CPU qui est garantie d'être accordée, de bien fonctionner avec le prefetching, etc. Par exemple, voir le commentaire d'Andy Glew ici:
2 votes
Le gros point faible de la réalisation rapide de chaînes de caractères en microcode était ... et (b) le microcode devenait de plus en plus désynchronisé à chaque génération, devenant de plus en plus lent jusqu'à ce que quelqu'un s'en charge pour le corriger. - Andy Glew
3 votes
Il est également intéressant de noter que les performances rapides des chaînes de caractères sont effectivement très pertinentes dans, par exemple, les méthodes du noyau Linux telles que
read()
etwrite()
qui copient des données dans l'espace utilisateur : le noyau ne peut pas (n'utilise pas) utiliser des registres ou un code SIMD, donc pour un memcpy rapide, il doit soit utiliser des charges/stores de 64 bits, soit, plus récemment, il utiliserarep movsb
ourep rmovd
s'ils sont détectés comme rapides sur l'architecture. Ils bénéficient donc grandement des déplacements importants sans avoir explicitement besoin d'utiliser les registresxmm
ouymm
.0 votes
Par curiosité, calculez-vous vos chiffres de bande passante deux fois la taille de la longueur de
memcpy
ou une fois? Autrement dit, votre chiffre est-il un chiffre de "bande passante mémoire" ou un chiffre de "bande passante memcpy"? Bien sûr, cela ne change pas les performances relatives entre les techniques, mais cela m'aide à comparer avec mon système.1 votes
@BeeOnRope J'utilise 2 fois la taille de la fonction
memcpy
, c'est-à-dire la bande passante mémoire. Comme vous avez le même processeur que moi, avez-vous testé mon code dans ma question à ce sujet? Si oui, avez-vous obtenu le même résultat? Vous devez compiler avec-mavx
en raison de ce bogue. Essayez les mêmes options de compilation exactes que j'ai utiliséesgcc -O3 -march=native -fopenmp foo.c
.0 votes
@Zboson - intéressant - alors vos chiffres semblent cohérents avec ma boîte pour le NT
memcpy
(environ 13 Go copiés, soit 26 Go/s de bande passante), mais pas pour lerep movsb
où je vois plus de 20 Go/s de bande passante, mais vous signalez seulement 15. Je vais essayer votre code. Au fait, je suppose que vous avez désactivé le turbo pour vos tests (c'est pourquoi vous signalez 2,6 GHz ?). Je l'ai fait, bien que j'aurais dû le mentionner explicitement dans ma réponse.0 votes
@Zboson - J'obtiens environ 19,5 Go/s et 23,5 Go/s pour
rep movsb
etmemcpy
respectivement avec votre code. Très curieusement, cela ne correspond pas à vos résultats, puisque nous avons le même processeur. Il y a toutes sortes de choses intéressantes comme un "turbo mémoire efficace" qui peuvent jouer un rôle important ici - laissez-moi jouer un peu. C'est avec le turbo désactivé. Avec le turbo activé, j'obtiens environ 20 contre 25. Le turbo semble aider la versionmemcpy
plus que la versionrep movs
.1 votes
Je obtiens des résultats plus proches des vôtres si je passe au gouverneur
powersave
: environ 17,5 Go/s contre 23,5 Go/s. C'est-à-dire que les performances derep movsb
chutent mais pas celles dememcpy
. En effet, des mesures répétées montrent qu'avec le gouverneurpowersave
, mon processeur ne fonctionne qu'à environ 2,3 GHz pour le benchmarkmovs
, mais à 2,6 GHz pour le benchmarkmemcpy
. Une partie significative de la différence dans votre cas est probablement expliquée par la gestion de l'alimentation. Fondamentalement, le turbo écoénergétique (désormais PET) utilise une heuristique pour déterminer si le code est "bloqué mémoire" et abaisse la fréquence du processeur car une haute fréquence est "inutile".1 votes
Alors,
rep movs
subit un traitement défavorable (en termes de performances, peut-être économise-t-il de l'énergie cependant!) de l’heuristique PET, peut-être parce que l'heuristique voit qu'il y a un long arrêt sur une instruction, tandis que la version AVX hautement déroulée exécute encore beaucoup d'instructions. J'ai déjà vu cela lors de tests d'un algorithme sur une plage de valeurs de paramètres : à une certaine valeur, il y a une chute de performances beaucoup plus importante que prévue : mais ce qui se passe, c'est que soudainement, le seuil PET était atteint et le processeur a diminué sa fréquence (ce qui nuit toujours aux performances).0 votes
@BeeOnRope Je n'ai pas désactivé Turbo dans mes tests. Pourquoi cela importait-il pour les opérations liées à la bande passante mémoire? Quoi qu'il en soit, je viens de le désactiver (j'ai vérifié qu'il était bien désactivé en exécutant un outil de mesure de fréquence personnalisé) et cela ne semble pas faire beaucoup de différence. Mais changer la gestion de l'alimentation fait une différence. Avec
performance
rep movsb
atteint jusqu'à 20 Go/s, mais avecpowersave
il atteint au maximum 17 Go/s. J'ai ajouté ces informations à la fin de ma question.0 votes
@BeeOnRope comment les paramètres d'économie d'énergie (PET) influent-ils lorsque le turbo est désactivé ? Je suis allé dans le BIOS et j'ai désactivé SpeedStep. Ne devrait-il pas exécuter le CPU à une fréquence fixe ? Pourquoi
powersave
ouperformance
importeraient-ils dans ce cas si le CPU fonctionne à une fréquence constante ?0 votes
Eh bien, PET est probablement un abus de langage car apparemment cela n'affecte pas seulement les fréquences supérieures à nominales, mais plutôt l'ensemble de la plage DVFS. Cela a du sens - ce n'est pas comme si la fréquence nominale était particulièrement spéciale : s'il est logique de la réduire à 2,6 GHz, il peut également être logique de la réduire à 2,3 ou 1,0 ou autre. Désactiver SpeedStep va probablement fonctionner, mais c'est facile à vérifier, il suffit d'exécuter
grep /proc/cpu MHz
quelques fois et d'observer les valeurs, ou de lancerturbostat
. J'ai exécuté le benchmark commeperf ./a.out
pour faire mon observation : cela vous donne l'effet en GHz pour le processus.0 votes
Si votre CPU est verrouillé,
powersave
etperformance
peut-être ne devraient pas importer (il reste la question des fréquences de l'uncore, qui sont indépendantes, mais aucun outil standard ne les rapporte, autant que je sache). De plus, il peut y avoir d'autres aspects d'économie d'énergie non directement liés à la fréquence qui sont contrôlés par ce paramètre (par exemple, l'agressivité du passage à des C-states plus élevés ?).0 votes
À propos du turbo, cela peut faire une différence significative pour les choses liées à la mémoire, car cela affecte les performances uncore et donc impacte la latence, puisque une grande partie de la latence d'un accès mémoire est un travail uncore, qui est accéléré par le turbo (mais c'est aussi complexe en raison de l'interaction entre les heuristiques d'économie d'énergie, et le fait que les fréquences uncore et core sont en partie indépendantes). Étant donné que nos puces semblent atteindre la limite réelle de la bande passante de la DRAM (c'est-à-dire pas une limite de concurrence-occupation comme indiqué dans la discussion sur les "plateformes limitées par la latence" ci-dessous), cela peut ne pas s'appliquer et je ne vois pas beaucoup d'effet sur mon CPU. @Zboson
0 votes
@Art pensez-vous que vous pourriez exécuter tinybenchmark (voir la réponse de BeeOnRope) sur votre système Ivy Bridge et ajouter les résultats à la fin de ma question ?
0 votes
@BeeOnRope. J'ai vérifié la fréquence. Avec
powersave
, le CPU reste inactif à 0,8 GHz même avec SpeedStep désactivé. Ce n'est qu'avecperformance
que le CPU est verrouillé à 2,6 GHz avec SpeedStep désactivé. Voir la mise à jour à la fin de ma question.0 votes
@Zboson - exactement, je me souviens de quelque chose de similaire : le pilote
intel_pstate
utilisera toujours les P-states pour contrôler la fréquence même si SS est désactivé dans le BIOS. Vous pouvez également utiliserintel_pstate=disabled
comme paramètre de démarrage pour le désactiver complètement, vous permettant ainsi d'utiliser la gestion de l'alimentation par défaut, y compris le gouverneur "utilisateur" qui définit la fréquence à ce que vous voulez (pas de fréquences turbo cependant). Anecdote intéressante : sansintel_pstate
, mon processeur ne fonctionnerait jamais au-dessus de 3,4 GHz (c'est-à-dire que les derniers 100 MHz du mode turbo étaient inaccessibles). Avecintel_pstate
, aucun problème.1 votes
Soit dit en passant, il y a un vrai terrier de lapin intéressant à descendre avec ces économies d'énergie : par exemple, exécuter deux benchmarks côte à côte peut donner lieu à plus de 2x de débit total (c'est-à-dire un "scalabilité superlinéaire" avec plus de threads, ce qui est vraiment bizarre) parce qu'un benchmark maintient une fréquence de cœur ou de non-cœur élevée ce qui aide l'autre, mais peut-être mérite-t-il une question entièrement distincte. Je pense que l'économie d'énergie est une partie de la performance
rep movsb
quelque peu plus pauvre, mais ce n'est pas toute l'histoire (même à MHz égal, c'est plus lent).1 votes
Soit dit en passant, j'ai mesuré la consommation d'énergie de
rep movsb
(en mode économie d'énergie à la fréquence la plus basse) par rapport àmemcpy
, mais la puissance (c'est-à-dire les watts) était seulement légèrement inférieure, et l'énergie totale consommée était plus élevée (car elle fonctionne plus longtemps). Il n'y a donc aucun avantage en termes d'économie d'énergie...2 votes
@BeeOnRope De toute évidence, il devrait y avoir une salle de discussion RFB-x86 (Demande de Bancs d'Essai - x86) dans le seul but de rétro-ingénierie des facteurs influençant les performances des processeurs x86.
1 votes
@Zboson - J'utilise des commandes comme
sudo cpupower -c 0,1,2,3 frequency-set -g performance
- selon ce que je comprends,cpuopwer
est la commande la plus à jour et maintenue pour la gestion de l'alimentation (elle peut également ajuster le "perf bias" sur les puces Intel récentes). En utilisant cette commande, passer en modeperformance
ne semble pas affecter le turbo. J'utilise ce script pour activer/désactiver le turbo, bien qu'il semble peut-être plus simple d'utiliser/sys/devices/system/cpu/intel_pstate/no_turbo
si vous utilisezintel_pstate
.0 votes
@BeeOnRope re : 'Essentiellement, le turbo efficace en énergie (ci-après PET) utilise une méthode heuristic pour déterminer si le code est "limité par l'arrêt de la mémoire" et réduit la vitesse du CPU car une fréquence élevée est "inutile"'. Des lectures complémentaires à ce sujet ? Je ne trouve aucun des mots-clés dans le Manuel d'optimisation.
0 votes
@Noah - c'était quelque chose que j'ai découvert ici sur SO en répondant à une question sur la raison pour laquelle
rep movsb
était plus lent que les instructions d'écriture de copie explicites : cet effet expliquait une partie de l'écart. Je ne suis pas au courant de toute discussion à ce sujet en dehors de SO : vous pourriez chercher cette question et la lier si vous la trouvez. Je n'ai pas pu la trouver mais je n'y ai pas passé beaucoup de temps et la recherche SO renvoie étrangement peu de résultats.