Использование AVX с GCC: __builtin_ia32_addpd256 не объявлен

Если я #include <immintrin.h> получаю эту ошибку:

ошибка: '__builtin_ia32_addpd256' не был объявлен в этой области

Я определил макросы __AVX__ и __FMA__, чтобы сделать AVX доступным, но, видимо, этого недостаточно. Нет ошибки, если я использую флаг компилятора -mavx вместо макросов, но это решение неприемлемо. Итак, что еще я должен определить, чтобы использовать AVX?


person Violet Giraffe    schedule 18.09.2013    source источник
comment
Возможно, вы захотите уточнить, что -mavx не является вариантом. В конце концов, использование avx-внутренностей довольно сложно, когда компилятору фактически не разрешено создавать код avx.   -  person Grizzly    schedule 18.09.2013


Ответы (2)


Вы не должны сами определять __AVX__ и __FMA__ - они определяются автоматически, когда вы включаете правильные параметры компилятора, например.

gcc -Wall -mavx ...

Вы можете проверить это сами, если вам интересно:

Нет AVX:

$ gcc -dM -E - < /dev/null | egrep "AVX|FMA"
$

AVX:

$ gcc -mavx -dM -E - < /dev/null | egrep "AVX|FMA"
#define __AVX__ 1
$

AVX + FMA:

$ gcc -mavx -mfma -dM -E - < /dev/null | egrep "AVX|FMA"
#define __AVX__ 1
#define __FMA__ 1
$
person Paul R    schedule 18.09.2013
comment
Я упомянул в вопросе, что использование -mavx неприемлемо. Тем не менее, спасибо за то, что показали способ увидеть определения. - person Violet Giraffe; 18.09.2013
comment
Извините - пропустил последнее предложение в вашем вопросе - как вы собираетесь скомпилировать код AVX, если вы не включите эту опцию компилятора, и зачем вам вообще это делать? - person Paul R; 18.09.2013
comment
Я рассчитываю сделать AVX объявления встроенных функций доступными с помощью правильных определений, и я ожидаю, что реализация будет связана из библиотеки времени выполнения. В чем проблема? Причина, по которой я не могу использовать параметры -m, заключается в том, что в этом случае компилятор автоматически векторизует мой код, используя указанный набор инструкций, что приводит к SIGILL на ЦП без поддержки AVX + FMA. Мне нужно, чтобы эти инструкции появлялись только там, где я явно использовал соответствующие встроенные функции. - person Violet Giraffe; 18.09.2013
comment
Внутренности так не работают, и они ни на что не ссылаются — общая идея заключается в том, что они генерируют встроенный код — если вы посмотрите на заголовки, вы увидите, что каждая встроенная функция сопоставляется с __builtin_XXX, которую, в свою очередь, использует компилятор. для генерации соответствующих встроенных кодов операций. Если вы не включите AVX, компилятор не сможет обработать __builtin_XXXs. - person Paul R; 18.09.2013
comment
Да, я это вижу, у меня проблемы с символом __builtin. Вы уверены, что это не штатная функция? - person Violet Giraffe; 18.09.2013
comment
Нет, это определенно не обычная функция - помните, что каждая встроенная функция обычно сопоставляется с одной инструкцией ЦП - вызов функции для каждой инструкции более чем уничтожит любую потенциальную выгоду от использования SIMD. - person Paul R; 18.09.2013
comment
@VioletGiraffe: внутренние элементы были бы совершенно бессмысленными, если бы они сопоставлялись с обычными (не встроенными) функциями, которые нужно снова связать. Для многих операций накладные расходы на вызов функции могут легко затмить затраты на саму операцию, особенно потому, что это запрещает оставлять данные в регистре ymm, в котором они в настоящее время находятся. - person Grizzly; 18.09.2013
comment
Похоже, что настоящая проблема здесь заключается в том, что вы пытаетесь создать общий код, который работает как на платформах AVX, так и на платформах, отличных от AVX, — вам может потребоваться попробовать другой подход для достижения этого. - person Paul R; 18.09.2013
comment
Да, мне придется задать еще один вопрос. Спасибо. - person Violet Giraffe; 18.09.2013

Правильным решением может быть наличие определенного файла, содержащего встроенную функцию процессора. И вы устанавливаете параметры -mavx -mfma только для этого файла. Программа сама определяет, какую версию вызывать во время выполнения.

Я использую помощники GCC, чтобы получить лучшую оптимизированную версию во время выполнения.

func_avx_fma.c

void domagic_avx_fma(...) {}

func_general.c

void domagic_general(...) {}

helper.c

void domagic_avx_fma(...);
void domagic_general(...);
typedef void (*domagic_func_t)(...);
domagic_func_t resolve_domagic()
{
     __builtin_cpu_init();
     if (__builtin_cpu_supports("avx") && __builtin_cpu_supports("fma")) {
         return domagic_avx_fma;
     }
     return domagic_general;
}
void domagic(...) __attribute__ ((ifunc ("resolve_domagic")));

программа.с

void domagic(...);
int main() { 
    domagic(...);
}

Скомпилировать

$ gcc -c func_avx_fma.c -o func_avx_fma.o -O3 -mfma -mavx
$ gcc -c func_general.c -o func_general.o -O3
$ gcc -c helper.c -o helper.o
$ ...

Этот подход отлично работает на x86 (x86_64), но не все цели поддерживают эти помощники.

person sergfc    schedule 11.04.2017