任何理由在64位CPU上使用32位整数进行常规操作?
我想知道是否在64位程序中继续使用int
(在x86和x86_64上是32位)是一个好主意,这个变量没有什么特别的,并且不需要像迭代计数器那样跨越2 ^ 64,或者如果最好使用与CPU的字大小相匹配的size_t
。
当然,如果你继续使用int
你可以节省一半的内存,这可能意味着有关CPU高速缓存的说法,但是我不知道在64位计算机上,每个32位数必须在使用前扩展到64位。
编辑:我用我的一个程序跑了一些测试(看到自己的答案,我仍然保持janneb的接受,但因为它是好的)。 事实证明,有显着的性能改进。
对于数组索引和指针算术,与指针大小相同的类型(通常是size_t和ptrdiff_t)会更好,因为它们避免了对寄存器进行零或符号扩展的需要。 考虑
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];
}
使用x86_64上的GCC 4.4 -O2生成以下asm:
.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
可以看出,具有int和unsigned int索引(onei和oneu)的版本需要额外的指令(movslq / mov)来对寄存器进行签名/零扩展。
正如在评论中提到的那样,缺点是对64位寄存器进行编码需要比32位部分更多的空间,从而导致代码大小膨胀。 其次,ptrdiff_t / size_t变量需要比等价的int更多的内存; 如果你有这样的数组,它肯定会影响性能,而不是避免零/符号扩展的相对小的好处。 如果不确定,个人资料!
在Cache方面,它会节省空间; 缓存处理数据块,而不管CPU是请求单个地址还是完整块等于缓存块大小。
所以如果你问32位数是否在64位机器的缓存里占用64位的空间,那么答案是否定的,他们仍然需要32位。 所以一般来说,它会为你节省一些空间,特别是当你使用频繁访问的大型数组时。
我个人认为,一个简单的int
看起来比size_t
简单,而且大多数编辑器不会识别size_t
类型,所以如果使用int
语法突出显示也会更好。 ;)
我正在编写一个小硬球模型。 源可以在github上找到。
我试图继续使用size_t
作为用作数组索引的变量, int
用于其他操作,与字大小无关。 性能提升非常显着:执行时间下降约27〜24。
上一篇: Any reason to use 32 bit integers for common operations on 64 bit CPU?