다음 루프는 정수 행렬을 다른 정수 행렬로 변환합니다. 흥미롭게 컴파일 할 때 출력 결과를 출력 행렬에 저장하는 명령어 인 movaps
을 생성합니다. 왜 gcc
이 이것을할까요?왜이 SSE2 프로그램 (정수)이 무브 랩 (float)을 생성합니까?
데이터 :
int __attribute__((aligned(16))) t[N][M]
, __attribute__((aligned(16))) c_tra[N][M];
루프 :
.L39:
lea rcx, [rsi+rdx]
movdqa xmm1, XMMWORD PTR [rdx]
add rdx, 16
add rax, 2048
movdqa xmm6, XMMWORD PTR [rcx+rdi]
movdqa xmm3, xmm1
movdqa xmm2, XMMWORD PTR [rcx+r9]
punpckldq xmm3, xmm6
movdqa xmm5, XMMWORD PTR [rcx+r10]
movdqa xmm4, xmm2
punpckhdq xmm1, xmm6
punpckldq xmm4, xmm5
punpckhdq xmm2, xmm5
movdqa xmm5, xmm3
punpckhqdq xmm3, xmm4
punpcklqdq xmm5, xmm4
movdqa xmm4, xmm1
punpckhqdq xmm1, xmm2
punpcklqdq xmm4, xmm2
movaps XMMWORD PTR [rax-2048], xmm5
movaps XMMWORD PTR [rax-1536], xmm3
movaps XMMWORD PTR [rax-1024], xmm4
movaps XMMWORD PTR [rax-512], xmm1
cmp r11, rdx
jne .L39
gcc -Wall -msse4.2 -masm="intel" -O2 -c -S
skylake
linuxmint
for(i=0; i<N; i+=4){
for(j=0; j<M; j+=4){
row0 = _mm_load_si128((__m128i *)&t[i][j]);
row1 = _mm_load_si128((__m128i *)&t[i+1][j]);
row2 = _mm_load_si128((__m128i *)&t[i+2][j]);
row3 = _mm_load_si128((__m128i *)&t[i+3][j]);
__t0 = _mm_unpacklo_epi32(row0, row1);
__t1 = _mm_unpacklo_epi32(row2, row3);
__t2 = _mm_unpackhi_epi32(row0, row1);
__t3 = _mm_unpackhi_epi32(row2, row3);
/* values back into I[0-3] */
row0 = _mm_unpacklo_epi64(__t0, __t1);
row1 = _mm_unpackhi_epi64(__t0, __t1);
row2 = _mm_unpacklo_epi64(__t2, __t3);
row3 = _mm_unpackhi_epi64(__t2, __t3);
_mm_store_si128((__m128i *)&c_tra[j][i], row0);
_mm_store_si128((__m128i *)&c_tra[j+1][i], row1);
_mm_store_si128((__m128i *)&c_tra[j+2][i], row2);
_mm_store_si128((__m128i *)&c_tra[j+3][i], row3);
}
}
어셈블리 코드를 생성
-mavx2
또는 -march=naticve
은 VEX 인코딩 : vmovaps
을 생성합니다.
실제로 인텔과 AMD는 코드 생성 연습을 권장합니다. 사실 최신 CPU의 경우 Intel은 정렬 된 & 정렬되지 않은로드가 동일한 성능 정렬의 쓰기가 더 중요하기 때문에 항상 "''movups''를 사용할 것을 권장합니다. [Intel] (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) 및 [AMD] (http : //developer.amd.com/resources/developer-guides-manuals/) 소프트웨어 최적화 안내서 –
@ChuckWalbourn'movups'와'movaps'는 Nehalem 이후로만 동일한 성능을 가지고 있습니다. 그러나 'movups'가 조작을 폴드 할 수 없기 때문에 오해의 소지가 있습니다. 실제로 'vmovaps'만이 쓸모 없습니다. 인텔과 AMD의 추천이 맞습니까? 하드웨어가 지원한다면'vmovups '를 항상 사용하는 것일 수도 있습니다. –
@ChuckWalbourn 지적한 인텔 설명서를 검색했지만 언급 한 권장 사항을 찾지 못했습니다. 어떤 부분을 언급하고 있습니까? 나는 또한'vmovaps'를 검색했는데 코드에 여러 번 표시되어 인텔이 여전히 그것을 사용합니다. –