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++).

Другие вопросы по тегам