Question

Theres sont deux endroits dans ma base de code où la même opération est répétée un très grand nombre de fois pour un grand nombre de données. Dans certains cas, il prend beaucoup de temps pour traiter ces derniers.

Je crois que l'utilisation de l'ESS pour mettre en œuvre ces boucles devraient améliorer leurs performances de manière significative, en particulier lorsque de nombreuses opérations sont effectuées sur le même ensemble de données, donc une fois que les données sont lues dans le cache d'abord, il ne doit pas y avoir de cache passe à côté de ce décrochage. Cependant, je ne suis pas sûr d'aller à ce sujet.

  • Y at-il un compilateur et OS de manière indépendante écrire le code pour tirer parti des instructions SSE? J'aime les intrinsics du VC, qui comprennent les opérations de l'ESS, mais je ne l'ai pas trouvé de solutions de cross compilateur.

  • Je dois encore soutenir une CPU qui soit ont pas ou soutien SSE limité (par exemple Intel Celeron). Y at-il un moyen d'éviter d'avoir à faire des différentes versions du programme, comme avoir une sorte de « linker de temps d'exécution » qui relie soit dans le code optimisé de base ou SSE en fonction de la CPU en cours d'exécution lorsque le processus est lancé?

  • Qu'en est-il d'autres extensions CPU, en regardant les jeux d'instructions de divers Intel et AMD CPU indique qu'il ya certains d'entre eux?

Était-ce utile?

La solution

Pour votre deuxième point, il existe plusieurs solutions aussi longtemps que vous pouvez séparer les différences dans les différentes fonctions:

  • pointeurs de fonction C bon vieux
  • liaison dynamique (qui repose généralement sur des pointeurs de fonction C)
  • si vous utilisez C ++, ayant différentes classes qui représentent le support pour différentes architectures et en utilisant des fonctions virtuelles peuvent aider énormément à ce sujet.

Notez que parce que vous souhaitez compterez sur les appels de fonction indirects, les fonctions abstraites les différentes opérations doivent généralement pour représenter la fonctionnalité de niveau un peu plus élevé, ou vous risquez de perdre tout ce que vous gagne obtenir de l'instruction optimisée dans les frais généraux d'appel (dans d'autres les mots ne abstraire les opérations SSE individuels -. abstraire le travail que vous faites)

Voici un exemple en utilisant des pointeurs de fonction:

typedef int (*scale_func_ptr)( int scalar, int* pData, int count);


int non_sse_scale( int scalar, int* pData, int count)
{
    // do whatever work needs done, without SSE so it'll work on older CPUs

    return 0;
}

int sse_scale( int scalar, in pData, int count)
{
    // equivalent code, but uses SSE

    return 0;
}


// at initialization

scale_func_ptr scale_func = non_sse_scale;

if (useSSE) {
    scale_func = sse_scale;
}


// now, when you want to do the work:

scale_func( 12, theData_ptr, 512);  // this will call the routine that tailored to SSE 
                                    // if the CPU supports it, otherwise calls the non-SSE
                                    // version of the function

Autres conseils

Bonne lecture sur le sujet: Arrêter la guerre jeu d'instructions

Bref aperçu: Désolé, il est impossible de résoudre votre problème de manière simple et plus compatible (Intel vs AMD)

.

Les valeurs intrinsèques de l'ESS travaillent avec c ++ visuel, et le compilateur GCC intel. Il n'y a pas de problème pour les utiliser ces jours-ci.

Notez que vous devez toujours garder une version de votre code qui n'utilise pas ESS et vérifiez constamment contre votre implémentation SSE.

Cela permet non seulement pour le débogage, il est également utile si vous voulez soutenir les processeurs ou les architectures qui ne prennent pas en charge vos versions SSE requis.

En réponse à votre commentaire:

  

Donc, en réalité, tant que je ne cherche pas à exécuter effectivement le code contenant des instructions non pris en charge, je vais bien, et je pouvais sortir avec un « if (see2Supported) {...} else {...} » commutateur de type?

Cela dépend. Il est très bien pour les instructions SSE d'exister dans le binaire aussi longtemps qu'ils ne sont pas exécutés. La CPU n'a pas de problème avec cela.

Toutefois, si vous activez le support SSE dans le compilateur, il échangera très probablement un certain nombre d'instructions « normales » pour leurs équivalents SSE (ops scalaire à virgule flottante, par exemple), de sorte que même des morceaux de votre non-SSE régulier le code va exploser sur un processeur qui ne le supporte pas.

Alors, que vous devez faire est le plus probable sur la compilation ou deux fichiers séparément, avec SSE activé et laissez-les contenir toutes vos routines SSE. Alors que le lien avec le reste de l'application, qui est compilé sans support SSE.

Au lieu de codage manuel une implémentation SSE alternative à votre code scalaire, je vous suggère fortement de jeter un oeil à OpenCL . Il est un système indépendant du fournisseur portable, multi-plateforme pour les applications de calcul intensif (et est très conforme à mot à la mode!). Vous pouvez écrire votre algorithme dans un sous-ensemble de C99 conçu pour les opérations vectorisées, ce qui est beaucoup plus facile que SSE codage manuel. Et le meilleur de tous, OpenCL va générer la meilleure mise en œuvre lors de l'exécution, soit d'exécuter sur le GPU ou sur la CPU. Donc, fondamentalement, vous obtenez le code SSE écrit pour vous.

  

Theres sont deux endroits dans ma base de code où la même opération est répétée un très grand nombre de fois pour un grand nombre de données. Dans certains cas, il prend beaucoup de temps pour traiter ces derniers.

Votre application ressemble exactement le genre de problème que OpenCL est conçu pour répondre. L'écriture des fonctions alternatives SSE améliorerait certainement la vitesse d'exécution, mais il est beaucoup de travail pour écrire et déboguer.

  

Y at-il un compilateur et OS de manière indépendante écrire le code pour tirer parti des instructions SSE? J'aime les intrinsics du VC, qui comprennent les opérations de l'ESS, mais je ne l'ai pas trouvé de solutions de cross compilateur.

Oui. Les SSE intrinsics ont été essentiellement normalisé par Intel, donc les mêmes fonctions fonctionnent de la même entre Windows, Linux et Mac (en particulier avec Visual C ++ et GNU g ++).

  

Je dois encore soutenir une CPU qui soit ont pas ou soutien SSE limité (par exemple Intel Celeron). Y at-il un moyen d'éviter d'avoir à faire des différentes versions du programme, comme avoir une sorte de « linker de temps d'exécution » qui relie soit dans le code optimisé de base ou SSE en fonction de la CPU en cours d'exécution lorsque le processus est lancé?

Vous pouvez le faire (par exemple. En utilisant dlopen()), mais il est une solution très complexe. serait beaucoup plus simple être (en C) pour définir une interface de fonctions et d'appeler la version appropriée de la fonction optimisée via le pointeur de fonction, ou en C ++ pour utiliser différentes classes d'implémentation, en fonction de la CPU détectée.

Avec OpenCL il est pas nécessaire de le faire, car le code est généré lors de l'exécution pour l'architecture donnée.

  

Qu'en est-il d'autres extensions CPU, en regardant les jeux d'instructions de divers Intel et AMD CPU montre de il y a certains d'entre eux?

Dans le jeu d'instructions SSE, il y a beaucoup de saveurs. Il peut être assez difficile de coder le même algorithme dans les différents sous-ensembles de SSE lorsque certaines instructions ne sont pas présentes. Je suggère (au moins pour commencer) que vous choisissez un niveau minimum pris en charge, comme SSE2, et revenir à la mise en œuvre scalaire sur des machines plus anciennes.

Ceci est également une situation idéale pour l'unité / tests de régression, ce qui est très important de vous assurer que vos différentes implémentations produisent les mêmes résultats. Avoir une suite de tests de données d'entrée et de bonnes données de sortie connues, et exécuter les mêmes données dans les deux versions de la fonction de traitement. Vous devrez peut-être d'avoir un test de précision pour le passage (ie. L'epsilon de différence entre le résultat et la réponse correcte est inférieure à 1e6, par exemple). Cela va grandement faciliter le débogage, et si vous construisez dans le calendrier haute résolution à votre cadre de test, vous pouvez comparer les améliorations de performance en même temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top