En utilisant le jeu d'instructions SSE
J'ai une boucle qui est écrit en C++ qui est exécutée pour chaque élément d'un grand tableau d'entiers. À l'intérieur de la boucle, je masque certains bits de l'entier, puis de trouver les valeurs min et max. J'ai entendu dire que si j'utilise les instructions SSE pour ces opérations, il sera beaucoup plus rapide par rapport à la normale de la boucle écrit à l'aide ET au niveau du bit , et si les autres conditions. Ma question est dois-je aller pour ces instructions SSE? Aussi, qu'advient-il si mon code s'exécute sur un processeur différent? Sera-il encore ou ces instructions de traitement spécifique?
- L'ESS est spécifique à l'architecture x86. Aussi, il y a de l'ESS versions (SSE2, SSE3, ...) et non pas toutes les caractéristiques de l'ESS sont disponibles sur chaque processeur. À l'aide de l'ESS correctement sera certainement livrer un énorme gain de performance; mais examiner attentivement si vous avez besoin que d'optimisation.
Vous devez vous connecter pour publier un commentaire.
SIMD, dont l'ESS est un exemple, permet de faire la même opération sur plusieurs blocs de données. Donc, vous ne serez pas obtenir quelque avantage de l'utilisation de l'ESS comme un droit de remplacement pour les opérations sur entiers, vous n'obtiendrez que les avantages si vous pouvez faire les opérations sur les éléments de données multiples à la fois. Cela implique le chargement de certaines valeurs de données qui sont contiguës en mémoire, de faire le traitement requis et ensuite pas à pas pour la prochaine série de valeurs dans le tableau.
Problèmes:
1 Si le chemin d'accès du code est la personne à charge sur les données en cours de traitement, SIMD devient beaucoup plus difficile à mettre en œuvre. Par exemple:
n'est pas facile de faire comme SIMD:
2 Si les données ne sont pas états contigus puis chargement des données dans les instructions SIMD est lourd
3 Du code du processeur spécifique. L'ESS n'est que sur IA32 (Intel/AMD) et pas tous les processeurs IA32 soutien de l'ESS.
Vous avez besoin pour analyser l'algorithme et les données pour voir si elle peut être de l'ESS avais et qui exige de savoir comment l'ESS fonctionne. Il y a beaucoup de documentation sur le site web d'Intel.
Ce genre de problème en est un parfait exemple de cas où un bien faible niveau profiler est essentiel. (Quelque chose comme VTune) Il peut vous donner un beaucoup plus informés idée de l'endroit où vos hotspots mensonge.
Je suppose, de ce que vous décrivez, c'est que votre point d'accès sera probablement branche de prédiction des défaillances résultant de min/max calculs à l'aide de if/else. Par conséquent, l'utilisation SIMD intrinsèques devrait vous permettre d'utiliser le min/max des instructions, cependant, il pourrait être intéressant de juste essayer d'utiliser un dépourvu de branches min/max caluculation à la place. Ce pourrait atteindre la plupart des gains avec moins de douleur.
Quelque chose comme ceci:
Si vous utilisez les instructions SSE, vous êtes évidemment limité de processeurs qui prennent en charge ces.
Cela signifie que x86, datant du Pentium 2 ou plus (ne me souviens pas exactement quand ils ont été introduits, mais c'est il y a longtemps)
SSE2, qui, autant que je puis me rappeler, est celle qui offre les opérations sur entiers, est un peu plus récente (Pentium 3? Bien que les premiers processeurs AMD Athlon ne supportent pas)
En tout cas, vous avez deux options pour l'utilisation de ces instructions. Soit écrire la totalité du bloc de code en assembleur (probablement une mauvaise idée. Qui fait qu'il est pratiquement impossible pour le compilateur d'optimiser votre code, et il est très difficile pour un être humain d'écrire efficace assembleur).
Vous pouvez également utiliser le intrinsèques à la disposition de votre compilateur (si ma mémoire est bonne, ils sont généralement définies dans xmmintrin.h)
Mais encore une fois, la performance peut ne pas s'améliorer. ESS code pose des exigences supplémentaires des données qu'il traite. Principalement, le seul à garder à l'esprit est que les données doivent être alignés sur 128 bits limites. Il devrait également y avoir peu ou pas de dépendances entre les valeurs chargées dans le même registre (128 bit ESS registre peut contenir 4 ints. L'ajout de la première et de la deuxième ensemble n'est pas optimale. Mais l'ajout de quatre entiers correspondant 4 ints dans un autre registre sera rapide)
Il peut être tentant d'utiliser une bibliothèque qui enveloppe tout le bas niveau de l'ESS jouer du violon, mais qui peut aussi ruiner toute possibilité de gain de performances.
Je ne sais pas comment bien l'ESS entier soutien des opérations à l'est, alors peut-être aussi un facteur qui peut limiter les performances. L'ESS est principalement destiné à accélérer les opérations en virgule flottante.
Si vous avez l'intention d'utiliser Microsoft Visual C++, vous devriez lire ceci:
http://www.codeproject.com/KB/recipes/sseintro.aspx
Nous avons mis en œuvre des traitements d'image de code, similaire à ce que vous décrivez, mais sur un tableau d'octets Dans l'ESS. L'accélération par rapport à du code C est considérable, selon la nature exacte de l'algorithme de plus d'un facteur de 4, de même en ce qui concerne le processeur Intel compilateur. Cependant, comme vous l'avez déjà mentionné que vous avez les inconvénients suivants:
La portabilité. Le code sera exécuté sur chaque processeur Intel comme le CPU, donc aussi de la DMLA, mais pas sur les autres Processeurs. Ce n'est pas un problème pour nous, car nous avons le contrôle de la cible matérielle. La commutation de compilateurs et même à une version 64 bits de l'OS peut également être un problème.
Vous avez une courbe d'apprentissage abrupte, mais j'ai trouvé que, après avoir à saisir les principes de l'écriture de nouveaux algorithmes n'est pas difficile.
La maintenabilité. La plupart de C ou de C++ les programmeurs n'ont pas la connaissance de l'assemblée/SSE.
Mon conseil pour vous est d'aller pour cela que si vous avez vraiment besoin d'amélioration de la performance, et vous ne pouvez pas trouver une fonction pour votre problème dans une bibliothèque comme les intel IPP, et si vous pouvez vivre avec les problèmes de portabilité.
Je peux dire de ma propre expérience que l'ESS apporte un énorme (4 et plus) speedup sur une plaine de c de la version du code (pas de asm inline, pas de intrinsèques utilisé) mais la main-assembleur optimisé peut battre généré par le Compilateur de l'assemblée si le compilateur ne peut pas comprendre ce que le programmeur a prévu (crois-moi, compilateurs ne pas couvrir l'ensemble des codes et ils ne le sera jamais).
Oh, et, le compilateur ne peut pas à chaque fois la mise en page des données qu'il fonctionne à la manière la plus rapide-vitesse possible.
Mais vous avez besoin de beaucoup de metier pour une accélération sur une Intel-compilateur (si possible).
Les instructions SSE ont été à l'origine seulement sur des puces d'Intel, mais récemment (depuis Athlon?) AMD prend en charge aussi bien, donc si vous n'code contre le jeu d'instructions SSE, vous devez être portable sur la plupart des x86 procs.
Cela étant dit, il peut ne pas être utile de votre temps pour apprendre l'ESS de codage, sauf si vous êtes déjà familier avec l'assembleur x86 est une option plus facile peut-être à vérifier que votre compilateur docs et voir si il y a des options pour permettre au compilateur de générer automatiquement l'ESS code pour vous. Certains compilateurs font très bien la vectorisation de boucles dans cette voie. (Vous n'êtes probablement pas surpris d'entendre que les compilateurs Intel faire un bon travail de cela 🙂
D'écrire un code qui permet au compilateur de comprendre ce que vous faites. GCC sera de comprendre et d'optimiser l'ESS code comme ceci:
Il suffit de ne pas oublier de s'-msse -msse2 sur votre construire des paramètres de!
Même si il est vrai que l'ESS est spécifique à certains processeurs (ESS peut être relativement à l'abri, SSE2 beaucoup moins dans mon expérience), vous pouvez détecter le PROCESSEUR lors de l'exécution, et de charger le code dynamiquement en fonction du PROCESSEUR cible.
SIMD intrinsèques (comme SSE2) peut accélérer ce genre de chose, mais prendre l'expertise nécessaires pour utiliser correctement. Ils sont très sensibles à l'alignement et le pipeline de latence; utilisation négligente peut faire encore pire qu'elle ne l'aurait été sans eux. Vous obtiendrez un beaucoup plus facile et la plus immédiate de l'accélération de la simple utilisation du cache de pré-chargement pour vérifier que tous les entiers sont en L1 dans le temps pour vous d'opérer sur eux.
À moins que votre fonction a besoin d'un débit supérieur à 100 000 000 d'entiers par seconde, SIMD n'est probablement pas la peine pour vous.
Juste pour ajouter brièvement de ce qui a été dit avant sur les différents ESS versions disponibles sur les différents Processeurs: Cela peut être vérifié en regardant la fonction correspondant drapeaux renvoyée par l'instruction CPUID (voir, par exemple, d'Intel et de la documentation pour les détails).
Ont un coup d'oeil à assembleur en ligne pour le C/C++, voici une DDJ article. Sauf si vous êtes certain à 100% que votre programme sera exécuté sur une plate-forme compatible, vous devez suivre les recommandations de nombreuses personnes ont donné ici.
Je suis d'accord avec les précédentes affiches. Les avantages peuvent être assez grande, mais pour l'obtenir, il peut exiger beaucoup de travail. Intel documentation sur ces instructions est sur les pages de 4ko. Vous voudrez peut-être vérifier EasySSE (c++ wrappers bibliothèque de plus de intrinsèques + exemples) libre à partir de Ocali Inc.
J'assume mon appartenance à cette EasySSE est clair.
Je ne recommande pas de faire vous-même, sauf si vous êtes assez compétent avec de l'assemblée. À l'aide de l'ESS sera, plus que probablement, exigent une réorganisation de vos données, comme Skizz points, et le bénéfice est souvent discutables.
Il serait probablement beaucoup mieux pour vous écrire de très petites boucles et de garder vos données très bien organisés, et seulement compter sur le compilateur de le faire pour vous. À la fois le processeur Intel Compilateur C et GCC (depuis la version 4.1) peut auto-vectorisation de votre code, et va sans doute faire un meilleur travail que vous. (Ajouter-ftree-vectoriser à votre CXXFLAGS.)
Modifier: une Autre chose que je dois mentionner, c'est que plusieurs compilateurs soutien assemblée intrinsèques, probablement, de l'OMI, être plus facile à utiliser que l'asm() ou __asm{} syntaxe.