2012-06-06 3 views
10

특별한 것이 없으며 실제로 반복 카운터처럼 2^64까지 확장 할 필요가없는 변수에 대해 64 비트 프로그램에서 int (x86과 x86_64 모두 32 비트)을 계속 사용하는 것이 좋습니다. 또는 CPU의 워드 크기와 일치하는 size_t을 사용하는 것이 더 나은 경우.64 비트 CPU에서 일반적인 작업을 수행 할 때 32 비트 정수를 사용해야하는 이유는 무엇입니까?

int을 계속 사용하면 메모리의 절반을 절약 할 수 있습니다. 이는 CPU 캐시에 관한 내용을 의미 할 수 있지만 64 비트 컴퓨터에서 32 비트를 64로 확장해야하는지는 모르겠습니다. 비트를 사용하기 전에.

편집 : 나는 내 프로그램으로 몇 가지 테스트를 실시했다. (self answer 참조, 여전히 좋기 때문에 janneb을 그대로 사용하고있다.) 중요한 성능 향상이 있음이 밝혀졌습니다.

+1

반복 카운터는 CPU 캐시에 있어서는 안됩니다. 그들은 등록부에 있어야합니다. –

+0

1. 컴파일러가 자동으로 많은 것을 수정한다고 생각합니다. 2. 왜 둘 사이의 성능을 테스트하는 프로그램을 작성하지 않습니까? – Shahbaz

+0

확실하지만 "그러나 64 비트 머신에서 매 32 비트 숫자를 64 비트로 확장하여 사용해야하는 경우"라는 사실을 알지 못합니다. 그리고 그것은 단지 하나의 예일뿐입니다. –

답변

4

배열 인덱스와 포인터 산술의 경우 포인터와 동일한 크기 (일반적으로 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/부호 확장을 피할 수있는 상대적으로 작은 이점보다 성능에 확실히 영향을 미칠 수 있습니다. 확실하지 않으면 프로필!

3

캐시 측면에서 보면 공간을 절약 할 수 있습니다. 캐시는 CPU가 단일 주소를 요청했는지 또는 캐시 블록 크기와 동일한 전체 청크인지 여부에 관계없이 데이터 블록을 처리합니다.

32 비트 숫자가 64 비트 컴퓨터의 캐시에서 64 비트 공간을 차지하는지 묻는다면 대답은 아니오, 그들은 여전히 ​​32 비트를 취합니다. 그래서 일반적으로, 당신이 등 액세스 빈도에 큰 배열을 사용하는 경우 특히, 당신에게 공간을 절약 할 수

내 개인적인 의견으로는

, 간단한 intsize_t보다 간단 보이는 대부분의 편집자는 구문 강조 그래서 size_t 유형을 인식하지 않습니다 int을 사용하면 더 좋습니다. ;)

+1

나는'size_t'을 즉시 인식하지 못하는 편집기 사용을 중단 할 것을 제안합니다! – Shahbaz

+2

많은 편집자 (MS Visual Studio, 울트라 편집, notepad ++, editplus)가 size_t를 인식하지 못하는 경우, 유형으로 강조 표시된 것을 구성 할 수없는 편집기 사용을 확실히 중단하십시오 :-) –

+0

. 하나는 유닉스/리눅스 환경에서 다음 안전, 그렇지 않으면 여전히 더 잘 엉망 : P는 어쨌든, 이것은 주요 포인트가 아니 었 안전 개발할 경우 : :) – xenodevil

0

이것은 컴파일러 개발자의 결정입니다.

int은 "정상적인"부호가있는 정수의 자연 유형입니다. 그것이 무엇인지 결정하는 것은 컴파일러의 몫입니다.
특정 플랫폼에서 64 비트 정수를 사용할 때 실질적인 이점이있는 경우 컴파일러 개발자는 int 64 비트를 사용해야합니다. 표준은 그것을 허용합니다.

컴파일러 개발자가 32 비트 정수를 고수하기로 결정했다면 일반적으로 그를 신뢰해야합니다.
드문 경우이지만, 상당한 최적화 노력을 한 후에 long이 더 잘 작동하는 것을 알 수 있습니다. 그런 다음 변경하고 싶을 수도 있습니다.

3

약간 hard spheres model을 코딩하고 있습니다. 출처는 github입니다.

배열의 색인으로 사용되는 변수에 size_t을 계속 사용하려고 시도했으며 단어 크기와 관련이없는 다른 작업을 수행하는 곳에서 int을 계속 사용하려고했습니다. 성능 향상은 이었습니다. : 실행 시간이 27 ~ 24 시간 감소합니다.

+0

문제를 보여줍니다 아주 좋은 실제 세계의 예 첫 번째 장소. +1 – hroptatyr

관련 문제