Подтвердить что ты не робот

Почему GCC или Clang не оптимизируют обратную к 1 инструкции при использовании быстрой математики

Кто-нибудь знает, почему GCC/Clang не будет оптимизировать функцию test1 в приведенном ниже примере кода, чтобы просто использовать только инструкцию RCPPS при использовании опции fast-math? Есть ли другой флаг компилятора, который будет генерировать этот код?

typedef float float4 __attribute__((vector_size(16)));

float4 test1(float4 v)
{
    return 1.0f / v;
}

Вы можете увидеть скомпилированный вывод здесь: https://goo.gl/jXsqat

4b9b3361

Ответ 1

Поскольку точность RCPPS намного ниже, чем float.

Опция включения этой оптимизации не подходит для части -ffast-math.

x86 целевые параметры руководства gcc говорит, что на самом деле это опция, которая (с -ffast-math) получает gcc для их использования (с итерацией Ньютона-Рафсона):

  • -mrecipЭта опция позволяет использовать инструкции RCPSS и RSQRTSS (и их векторизованные варианты RCPPS и RSQRTPS) с дополнительным Newton-Raphson шаг для повышения точности вместо DIVSS и SQRTSS (и их векторизованные варианты) для плавающей запятой с одинарной точностью аргументы. Эти инструкции генерируются только тогда, когда -funsafe-math-optimizations активируется вместе с -finite-math-only и -fno-trapping-math. Заметим, что, хотя пропускная способность последовательности выше пропускной способности невзаимной инструкции, точность последовательности может быть уменьшена на величину до 2 ульт (т.е. обратный к 1.0 равен 0.99999994).

    Обратите внимание, что GCC реализует 1.0f/sqrtf (x) в терминах RSQRTSS (или RSQRTPS) уже с -ffast-math (или вышеупомянутой опционной комбинацией), и не требуется -mrecip.

    Также обратите внимание, что GCC испускает вышеприведенную последовательность с дополнительным шагом Ньютона-Рафсона для векторизованного однопотокового деления и векторизованный sqrtf (x) уже с -ffast-math (или вышеупомянутый вариант комбинация), и не требуется -mrecip.

  • -mrecip=opt

Эта опция определяет, какие команды взаимной оценки могут использоваться. opt - список опций, разделенных запятыми, которым может предшествовать от '! для инвертирования опции:

’all’
      Enable all estimate instructions.
‘default’
    Enable the default instructions, equivalent to -mrecip.
‘none’
    Disable all estimate instructions, equivalent to -mno-recip.
‘div’
    Enable the approximation for scalar division.
‘vec-div’
    Enable the approximation for vectorized division.
‘sqrt’
    Enable the approximation for scalar square root.
‘vec-sqrt’
    Enable the approximation for vectorized square root. 

Так, например, -mrecip = all,! sqrt разрешает все обратные аппроксимации, за исключением квадратного корня.

Обратите внимание, что новый дизайн Skylake от Intel еще больше улучшает производительность разделения FP, до задержки 8-11 c, пропускную способность 1/3c. (Или один на 5c пропускную способность для векторов 256b, но та же латентность для vdivps). Они расширили разделители, поэтому AVX vdivps ymm теперь имеет ту же задержку, что и для векторов 128b.

(SnB to Haswell сделал 256b div и sqrt с удвоенной пропускной способностью латентности/пропускной способности, поэтому они, очевидно, имели только разделители шириной 128b.) Skylake также конвейерирует обе операции больше, поэтому около 4 операций div могут быть в полете. sqrt работает быстрее.

Итак, через несколько лет, когда Skylake широко распространен, стоило бы делать RCPPS, если вам нужно разделить одно и то же несколько раз. RCPPS, а пара fma может иметь чуть более высокую пропускную способность, но хуже латентность. Кроме того, vdivps - только один uop; поэтому будет доступно больше ресурсов исполнения, чтобы вещи происходили одновременно с делением.

Остается посмотреть, как будет выглядеть первоначальная реализация AVX512. Предположительно RCPPS и пара FMA для итераций Newton-Raphson будут побеждать, если производительность подразделения FP является узким местом. Если пропускная способность uop является узким местом, и в то время как подразделения находятся в полете, есть еще много работы, vdivps zmm, вероятно, все еще хорош (если, конечно, один и тот же делитель не используется повторно).