2013-03-23 2 views
13

Я задам свой вопрос, представив пример. Теперь у меня есть функция, называемая do_something().Каким образом можно использовать разные версии SSE-встроенных функций в GCC?

Имеет три версии: do_something(), do_something_sse3() и do_something_sse4(). Когда моя программа запустится, она обнаружит функцию ЦП (см., Поддерживает ли она SSE3 или SSE4) и вызовет одну из трех версий соответственно.

Проблема заключается в том: Когда я построю свою программу с GCC, я должен установить -msse4 для do_something_sse4() компиляции (например, для заголовка файла <smmintrin.h> должны быть включены).

Однако, если я установил -msse4, то gcc разрешено использовать инструкции SSE4, а некоторые свойства в do_something_sse3() также переведены в некоторые инструкции SSE4. Поэтому, если моя программа работает на процессоре, который поддерживает только SSE3 (но не SSE4), он вызывает «незаконную инструкцию» при звонках do_something_sse3().

Возможно, у меня есть плохая практика. Не могли бы вы дать некоторые предложения? Благодарю.

+5

Я думаю, что стандартный подход заключается в компиляции различных версий в отдельных единицах компиляции. – Mysticial

+0

@Mysticial, сначала спасибо за редактирование моего вопроса. Насколько я понимаю, «скомпилировать разные версии в отдельных единицах компиляции» означает: поместить все 'do_things_sse4' в файл' functios_sse4.c' и скомпилировать его с помощью опции '-msse4'; и скомпилируйте 'functions_sse3.c' с' -msse3'. Я попробую это. (Возможно, мне придется восстановить мои коды, которые были первоначально написаны для MSVC) – shengbinmeng

+0

Да, это именно то, что я имел в виду. :) – Mysticial

ответ

9

Я думаю, что кончик мистического является штраф, но если вы действительно хотите сделать это в файле один, вы можете использовать соответствующую pragmas, например:

#pragma GCC target("sse4.1") 

GCC 4.4 требуется, Afair ,

+0

Благодарю вас за это предложение. Я также попробую директиву '# pragma' позже. – shengbinmeng

+0

Невозможно включить smmintrin.h даже с #pragma GCC target ("sse4") – Trass3r

0

Вот пример составления отдельного файла объекта для каждого параметра оптимизации: http://notabs.org/lfsr/software/index.htm

Но даже этот метод терпит неудачу, когда оптимизация времени НКУ ссылка (-flto) используется. Итак, как можно создать единый исполняемый файл с полной оптимизацией для разных процессоров? Единственное решение, которое я могу найти, это использовать директивы include, чтобы файлы C отображались как единый блок компиляции, так что -flto не требуется. Вот пример использования этого метода: http://notabs.org/blcutil/index.htm

2

Я думаю, вы хотите создать так называемый «диспетчер процессора». У меня есть одна работающая (насколько я знаю) для GCC, но у меня нет работы с Visual Studio.
cpu dispatcher for visual studio for AVX and SSE

Я хотел бы проверить vectorclass Agner противотуманными в и файл 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 
0

Если вы используете GCC 4.9 или выше на i686 или x86_64 машины, то вы должны быть возможность использования встроенных функций независимо от ваших опций -march=XXX и -mXXX. Вы можете написать свой do_something() соответственно:

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

Вы должны предоставить HasSSE2(), HasSSSE3() и друзей. Также см. Intrinsics for CPUID like informations?.

См. Также GCC Issue 57202 - Please make the intrinsics headers like immintrin.h be usable without compiler flags. Но я не считаю, что эта функция работает. Я регулярно сталкиваюсь с сбоями компиляции, потому что GCC не делает доступными встроенные функции.