Intel SSE/AVX/FMA 내장 함수를 사용하여 일부 수학 함수에 대해 SSE/AVX 명령어를 완벽하게 인라이닝 할 수 있습니다.컴파일러가 내장 어셈블리에 대해 생성 한 문제
다음 코드가 -march = - 64 -03 -mfma
std_fma(float, float, float): # @std_fma(float, float, float)
vfmadd213ss xmm0, xmm1, xmm2
ret
_fma(float, float, float): # @_fma(float, float, float)
vxorps xmm3, xmm3, xmm3
vmovss xmm0, xmm3, xmm0 # xmm0 = xmm0[0],xmm3[1,2,3]
vmovss xmm1, xmm3, xmm1 # xmm1 = xmm1[0],xmm3[1,2,3]
vmovss xmm2, xmm3, xmm2 # xmm2 = xmm2[0],xmm3[1,2,3]
vfmadd213ss xmm0, xmm1, xmm2
ret
_sqrt(float): # @_sqrt(float)
vsqrtss xmm0, xmm0, xmm0
ret
와
#include <cmath>
#include <immintrin.h>
auto std_fma(float x, float y, float z)
{
return std::fma(x, y, z);
}
float _fma(float x, float y, float z)
{
_mm_store_ss(&x,
_mm_fmadd_ss(_mm_load_ss(&x), _mm_load_ss(&y), _mm_load_ss(&z))
);
return x;
}
float _sqrt(float x)
{
_mm_store_ss(&x,
_mm_sqrt_ss(_mm_load_ss(&x))
);
return x;
}
연타 3.9 발생 조립체_sqrt
대해 생성 된 코드는 잘 동안을 감안할 (절대적으로 사용되지 않는 xmm3 레지스터를 0으로 설정하는) vxorps
및 과 비교하여 movss
명령어가 _fma
인 경우 불필요합니다 (r 컴파일러 극한 STD에 엘리 여기 -march = - 64 -03 -mfma
std_fma(float, float, float):
vfmadd132ss xmm0, xmm2, xmm1
ret
_fma(float, float, float):
vinsertps xmm1, xmm1, xmm1, 0xe
vinsertps xmm2, xmm2, xmm2, 0xe
vinsertps xmm0, xmm0, xmm0, 0xe
vfmadd132ss xmm0, xmm2, xmm1
ret
_sqrt(float):
vinsertps xmm0, xmm0, xmm0, 0xe
vsqrtss xmm0, xmm0, xmm0
ret
과 함께 :: FMA)
GCC의 6.2 발생 조립체 불필요한 vinsertps
지시 많다
근무 예 : XMM의 정합에 https://godbolt.org/g/q1BQym
기본 64 호출 규칙 패스 부동 소수점 함수 인수 sters이므로 vmovss
및 vinsertps
지침을 삭제해야합니다. 왜 언급 된 컴파일러가 여전히 그들을 방출합니까? 인라인 어셈블리없이 제거 할 수 있습니까?
또한 _mm_store_ss
대신 여러 개의 호출 규칙을 사용하려고 시도했지만 아무런 변화가 없었습니다.
intrinsic'_mm_load_ss '의 결과는 첫 번째 요소에 32 비트 부동 소수점 값이있는 128 비트 벡터이고 다른 세 요소에는 0입니다. 이것이 불필요한 지침이하는 일이며 다른 세 요소를 0으로 설정합니다. 컴파일러는 이러한 요소가 사용되지 않았 음을 감지하고 함수가 반환 할 때 결국 파기되는 것을 감지 할만큼 똑똑하지 않지만 요청한 작업을 수행하고 있습니다. 그러나 이미 FMA 케이스에 대한 완벽한 솔루션을 갖고있는 것으로 보입니다. –
이것은 정말로 나쁘다. 컴파일러는'* _ss' 내장 함수를 사용하기 때문에 컴파일러가 알아야한다. – plasmacel
AFAIK, 유일한 해결책은 그렇게하지 않는 것입니다. (그리고 저는 이것이 http://stackoverflow.com/questions/39318496/how-to-merge-a-scalar-into-a-vector-without- 컴파일러 - 낭비 - 명령). 일부 경우 Clang은 상위 요소가 사용되지 않았으며이를 만지지 않을 수 있음을 확인했습니다 (링크 된 질문 참조). 옵션을 사용하여 스칼라 코드에 적용 할 수있는 경우 ('-mfma' 또는'-ffast-math'가 아닌) FMA를 사용하도록 컴파일러를 얻을 수 있지만, 지금은 무엇을 잊어 버렸고 지금 당장이를 살펴볼 시간이 없습니다. 'std :: fma'가 완벽하게 인라인되기 때문에 그냥 사용하십시오. –