Quelle est la bonne façon d’utiliser différentes versions des composants insortingnsèques de SSE dans GCC?

Je vais poser ma question en donnant un exemple. Maintenant, j’ai une fonction appelée do_something() .

Il existe trois versions: do_something() , do_something_sse3() et do_something_sse4() . Lorsque mon programme sera exécuté, il détectera la fonctionnalité de la CPU (vérifiera s’il prend en charge SSE3 ou SSE4) et appellera l’une des trois versions en conséquence.

Le problème est le suivant: lorsque je construis mon programme avec GCC, je dois définir -msse4 pour que do_something_sse4() compilé (par exemple, pour que le fichier d’en-tête soit inclus).

Cependant, si je -msse4 , alors gcc est autorisé à utiliser les instructions SSE4, et certains éléments insortingnsèques dans do_something_sse3() sont également traduits en instructions SSE4. Ainsi, si mon programme fonctionne sur un processeur ne prenant en charge que SSE3 (mais pas SSE4), il provoque une “instruction illégale” lorsque vous appelez do_something_sse3() .

J’ai peut-être une mauvaise pratique. Pourriez-vous donner quelques suggestions? Merci.

Je pense que le conseil de Mystical convient, mais si vous voulez vraiment le faire dans un fichier, vous pouvez utiliser les pragmas appropriés, par exemple:

 #pragma GCC target("sse4.1") 

GCC 4.4 est nécessaire, AFAIR.

Je pense que vous voulez construire ce qu’on appelle un “répartiteur de CPU”. J’en ai un qui fonctionne (pour autant que je sache) pour GCC mais qui ne fonctionne pas avec Visual Studio.
Répartiteur CPU pour Visual Studio pour AVX et SSE

Je voudrais vérifier la classe de vecteur d’Agner Fog et le fichier dispatch_example.cpp http://www.agner.org/optimize/#vectorclass

 g++ -O3 -msse2 -c dispatch_example.cpp -od2.o g++ -O3 -msse4.1 -c dispatch_example.cpp -od5.o g++ -O3 -mavx -c dispatch_example.cpp -od8.o g++ -O3 -msse2 instrset_detect.cpp d2.o d5.o d8.o 

Voici un exemple de compilation d’un fichier object distinct pour chaque paramètre d’optimisation: http://notabs.org/lfsr/software/index.htm

Mais même cette méthode échoue lorsque l’optimisation du temps de liaison gcc (-flto) est utilisée. Alors, comment un seul exécutable peut-il être construit avec une optimisation complète pour différents processeurs? La seule solution que je puisse trouver est d’utiliser les directives d’inclusion pour que les fichiers C se comportent comme une seule unité de compilation, de sorte que l’option -flto ne soit pas nécessaire. Voici un exemple utilisant cette méthode: http://notabs.org/blcutil/index.htm

Si vous utilisez GCC 4.9 ou une version ultérieure sur une machine i686 ou x86_64, vous êtes censé être en mesure d’utiliser des éléments insortingnsèques quelles que soient vos -march=XXX et -mXXX . Vous pouvez écrire votre do_something() conséquence:

 void do_something() { byte temp[18]; if (HasSSE2()) { const __m128i i = _mm_loadu_si128((const __m128i*)(ptr)); ... } else if (HasSSSE3()) { const __m128i MASK = _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3); _mm_storeu_si128(reinterpret_cast<__m128i*>(temp), _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)(ptr)), MASK)); } else { // Do the byte swap/endian reversal manually ... } } 

Vous devez fournir HasSSE2() , HasSSSE3() et des amis. Voir aussi Insortingnsics for CPUID comme informations? .

Voir également le numéro 57202 de GCC – Faites en sorte que les en-têtes insortingnsèques comme imminsortingn.h soient utilisables sans les indicateurs de compilateur . Mais je ne crois pas que la fonctionnalité fonctionne. Je rencontre régulièrement des échecs de compilation car GCC ne met pas à disposition des composants insortingnsèques.