g++ 6.3, суммирование по Кахану по внутренним признакам avx сериализуется с ключевым словом volatile
Используя avx intrinsics и алгоритм суммирования Кахана, я попробовал это (только часть "сумматора"):
void add(const __m256 valuesToAdd)
{
volatile __m256 y = _mm256_sub_ps(valuesToAdd, accumulatedError);
volatile __m256 t = _mm256_add_ps(accumulator,y);
accumulatedError = _mm256_sub_ps( _mm256_sub_ps(t,accumulator),y);
accumulator = t;
}
ошибки нет, но когда я проверяю дизассемблирование (запись perf, отчет в ubuntu), он показывает, что все элементы аккумулятора, переменные y и накопленного Error вычисляются по одному скалярным способом.
Вопрос: Как можно определить внутреннюю переменную, которая может сохранять свой "порядок операций" и все еще использоваться (как векторизованный) в внутренней инструкции без оптимизации?
Чтобы убедиться, что он действительно скалярный, я удалил volatile, оно стало быстрее.
Есть ли способ сказать gcc, что мне нужна векторизованная переменная / код, но больше ничего не нужно трогать?
1 ответ
Если вы хотите явно предотвратить ассоциативную математическую оптимизацию, не используйте volatile
но отключите их, используя атрибут функции:
__attribute__ ((optimize("no-fast-math")))
inline void add(const __m256 &valuesToAdd)
{
__m256 y = _mm256_sub_ps(valuesToAdd, accumulatedError);
__m256 t = _mm256_add_ps(accumulator, y);
accumulatedError = _mm256_sub_ps(_mm256_sub_ps(t, accumulator), y);
accumulator = t;
}
Живая Демо. Поиграйте с флагами и атрибутами компиляции. Этот атрибут, похоже, не работает с clang (я думаю, что есть что-то эквивалентное, но ваш вопрос был специфичен для g++).