나는 다음과 같은 조회 및 보간 코드를 최적화해야합니다. (128 사이즈 플로트 테이블) Windows에서는 인텔 컴파일러, OSX에서는 GCC, 네온 OSX에서는 GCC와 함께 사용됩니다.SSE/NEON 테이블 조회 최적화
for(unsigned int i = 0 ; i < 4 ; i++)
{
const int iIdx = (int)m_fIndex[i];
const float frac = m_fIndex - iIdx;
m_fResult[i] = sftable[iIdx].val + sftable[iIdx].val2 * frac;
}
나는 모든 것을 sse/neon으로 vecorized했다. 내가 테이블 액세스와 정렬 메모리로 이동이 실제 병목 현상이 여기에 있다고 생각
VEC_INT iIdx = VEC_FLOAT2INT(m_fIndex);
VEC_FLOAT frac = VEC_SUB(m_fIndex ,VEC_INT2FLOAT(iIdx);
m_fResult[0] = sftable[iIdx[0]].val2;
m_fResult[1] = sftable[iIdx[1]].val2;
m_fResult[2] = sftable[iIdx[2]].val2;
m_fResult[3] = sftable[iIdx[3]].val2;
m_fResult=VEC_MUL(m_fResult,frac);
frac[0] = sftable[iIdx[0]].val1;
frac[1] = sftable[iIdx[1]].val1;
frac[2] = sftable[iIdx[2]].val1;
frac[3] = sftable[iIdx[3]].val1;
m_fResult=VEC_ADD(m_fResult,frac);
(매크로는 SSE/네온 명령어로 변환). 나는 어셈블러와 잘 모르지만 unpcklps 및 MOV 많이 있습니다 :
10026751 mov eax,dword ptr [esp+4270h]
10026758 movaps xmm3,xmmword ptr [eax+16640h]
1002675F cvttps2dq xmm5,xmm3
10026763 cvtdq2ps xmm4,xmm5
10026766 movd edx,xmm5
1002676A movdqa xmm6,xmm5
1002676E movdqa xmm1,xmm5
10026772 psrldq xmm6,4
10026777 movdqa xmm2,xmm5
1002677B movd ebx,xmm6
1002677F subps xmm3,xmm4
10026782 psrldq xmm1,8
10026787 movd edi,xmm1
1002678B psrldq xmm2,0Ch
10026790 movdqa xmmword ptr [esp+4F40h],xmm5
10026799 mov ecx,dword ptr [eax+edx*8+10CF4h]
100267A0 movss xmm0,dword ptr [eax+edx*8+10CF4h]
100267A9 mov dword ptr [eax+166B0h],ecx
100267AF movd ecx,xmm2
100267B3 mov esi,dword ptr [eax+ebx*8+10CF4h]
100267BA movss xmm4,dword ptr [eax+ebx*8+10CF4h]
100267C3 mov dword ptr [eax+166B4h],esi
100267C9 mov edx,dword ptr [eax+edi*8+10CF4h]
100267D0 movss xmm7,dword ptr [eax+edi*8+10CF4h]
100267D9 mov dword ptr [eax+166B8h],edx
100267DF movss xmm1,dword ptr [eax+ecx*8+10CF4h]
100267E8 unpcklps xmm0,xmm7
100267EB unpcklps xmm4,xmm1
100267EE unpcklps xmm0,xmm4
100267F1 mulps xmm0,xmm3
100267F4 movaps xmmword ptr [eax+166B0h],xmm0
100267FB mov ebx,dword ptr [esp+4F40h]
10026802 mov edi,dword ptr [esp+4F44h]
10026809 mov ecx,dword ptr [esp+4F48h]
10026810 mov esi,dword ptr [esp+4F4Ch]
10026817 movss xmm2,dword ptr [eax+ebx*8+10CF0h]
10026820 movss xmm5,dword ptr [eax+edi*8+10CF0h]
10026829 movss xmm3,dword ptr [eax+ecx*8+10CF0h]
10026832 movss xmm6,dword ptr [eax+esi*8+10CF0h]
1002683B unpcklps xmm2,xmm3
1002683E unpcklps xmm5,xmm6
10026841 unpcklps xmm2,xmm5
10026844 mulps xmm2,xmm0
10026847 movaps xmmword ptr [eax+166B0h],xmm2
승리에 SSE 버전과 많은 혜택이없는 프로파일 링.
개선 할만한 방법이 있습니까? 네온/gcc가 부작용이 예상됩니까?
현재 저는 첫 번째 부분을 vecorized로 만들고 컴파일러 최적화의 이점이되기를 희망하면서 루프에서 테이블 판독 및 보간을 수행하는 것을 고려합니다.
그냥 보면 첫 번째 코드 집합을 작성하는 데 매우 긴 명령 집합처럼 보입니다. –
이렇게하기 위해서, AVX2 (! - Haswell 만)는 큰 (메모리 내) 테이블의 검색을 위해'VGATHER' 명령어 군을 제공 받았습니다. 인텔에서는 SSE/AVX의 셔플을 통해 작은 테이블 검색을 수행 할 수 있습니다 (단, 부동 테이블의 경우 4/8 이하). SSE/AVX 규정에 맞지 않는 항목이 테이블에있는 경우에만 가능합니다. ARM NEON은 VTBL을 통해 동일한 작업을 수행 할 수 있습니다 (테이블은 최대 4 개의 네온 규정에 포함될 수 있으므로 다시 8 개의 부동 소수점에 포함될 수 있습니다). –
불행히도 최대 호환성이 필요하므로 나에게 최적화가 필요하지 않습니다. – evitan