Подразумевает передачу сигналов SIMD (SSE/AVX) с помощью GCC
Мне удалось преобразовать большую часть моего SIMD-кода в векторные расширения GCC. Однако я не нашел хорошего решения для трансляции следующим образом
__m256 areg0 = _mm256_broadcast_ss(&a[i]);
Я хочу сделать
__m256 argeg0 = a[i];
Если вы видите мой ответ в Mutiplying vector константой, используя SSE Мне удалось получить трансляции, работающие с другим регистром SIMD. Следующие работы:
__m256 x,y;
y = x + 3.14159f; // broadcast x + 3.14159
y = 3.14159f*x; // broadcast 3.14159*x
но это не сработает:
__m256 x;
x = 3.14159f; //should broadcast 3.14159 but does not work
Как я могу сделать это с помощью GCC?
Ответы
Ответ 1
Я думаю, что в настоящее время нет прямого пути, и вы должны обойти его с помощью синтаксиса, который вы уже заметили:
__m256 zero={};
__m256 x=zero+3.14159f;
Это может измениться в будущем, если мы сможем согласовать хороший синтаксис, см. PR 55726.
Обратите внимание: если вы хотите создать вектор { s, s, ... s }
с непостоянным float s
, вышеприведенная техника работает только с целыми числами или с поплавками и -fno-signed-zeros
. Вы можете настроить его на __m256 x=s-zero;
, и он будет работать, если вы не используете -frounding-math
. Последняя версия, предложенная Z бозоном, - это __m256 x=(zero+1.f)*s;
, которая должна работать в большинстве случаев (за исключением, возможно, параноидального компилятора о sNaN).
Ответ 2
Оказывается, что с точной моделью с плавающей запятой (например, с -O3
) GCC не может упростить x+0
до x
из-за подписанного нуля. Таким образом, x = zero+3.14159f
создает неэффективный код. Однако GCC может упростить 1.0*x
до просто x
, поэтому эффективное решение в этом случае есть.
__m256 x = ((__m256){} + 1)*3.14159f;
https://godbolt.org/g/5QAQkC
Подробнее см. этот ответ.
Более простое решение - это просто x = 3.14159f - (__m256){}
, потому что x - 0 = x
независимо от подписанного нуля.