배열 인덱스와 포인터 산술의 경우 포인터와 동일한 크기 (일반적으로 size_t와 ptrdiff_t)의 형식은 레지스터를 0 또는 부호 확장 할 필요가 없기 때문에 더 좋을 수 있습니다.
가 가 가
가 알 수있는 바와 같이, INT 및 부호없는 INT 지수 버전 (onei하고 oneu) 추가를 필요로
.p2align 4,,15
.globl onei
.type onei, @function
onei:
.LFB3:
.cfi_startproc
movslq %esi,%rsi
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE3:
.size onei, .-onei
.p2align 4,,15
.globl oneu
.type oneu, @function
oneu:
.LFB4:
.cfi_startproc
mov %esi, %esi
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE4:
.size oneu, .-oneu
.p2align 4,,15
.globl onep
.type onep, @function
onep:
.LFB5:
.cfi_startproc
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE5:
.size onep, .-onep
.p2align 4,,15
.globl ones
.type ones, @function
ones:
.LFB6:
.cfi_startproc
movss (%rdi,%rsi,4), %xmm0
ret
.cfi_endproc
.LFE6:
.size ones, .-ones
다음 ASM이 발생 x86_64의에 GCC 4.4 -O2로
float onei(float *a, int n)
{
return a[n];
}
float oneu(float *a, unsigned n)
{
return a[n];
}
float onep(float *a, ptrdiff_t n)
{
return a[n];
}
float ones(float *a, size_t n)
{
return a[n];
}
고려 명령 (movslq/mov)을 사용하여 레지스터에 부호를 붙이거나 0으로 확장합니다.
주석에서 언급했듯이 64 비트 레지스터를 인코딩 할 때 32 비트 부분보다 더 많은 공간이 필요하며 코드 크기가 커진다는 단점이 있습니다. 둘째, ptrdiff_t/size_t 변수는 동등한 int보다 더 많은 메모리가 필요합니다. 이러한 배열을 사용하면 0/부호 확장을 피할 수있는 상대적으로 작은 이점보다 성능에 확실히 영향을 미칠 수 있습니다. 확실하지 않으면 프로필!
반복 카운터는 CPU 캐시에 있어서는 안됩니다. 그들은 등록부에 있어야합니다. –
1. 컴파일러가 자동으로 많은 것을 수정한다고 생각합니다. 2. 왜 둘 사이의 성능을 테스트하는 프로그램을 작성하지 않습니까? – Shahbaz
확실하지만 "그러나 64 비트 머신에서 매 32 비트 숫자를 64 비트로 확장하여 사용해야하는 경우"라는 사실을 알지 못합니다. 그리고 그것은 단지 하나의 예일뿐입니다. –