我想知道在64位程序上继续使用int
(在x86和x86_64上都是32位)对于没有什么特殊的变量并且不需要跨越2 ^的变量是个好主意64,像迭代计数器一样,或者最好使用与CPU的字大小相匹配的size_t
。
当然,如果你继续使用int
,你可以节省一半的内存,这可能意味着谈论CPU缓存,但我不知道如果在64位机器上每32位数都必须在任何使用之前扩展到64位。
编辑: 我已经用我的程序进行了一些测试(参见self answer,我仍然保持janneb的接受,因为它很好)。事实证明,性能有了显着提升。
答案 0 :(得分:4)
对于数组索引和指针算法,与指针大小相同的类型(通常是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更多的内存;如果你有这样的数组,它肯定会影响性能远远超过避免零/符号扩展的相对较小的好处。如果不确定,简介!
答案 1 :(得分:3)
就Cache而言,它将节省空间;缓存处理数据块,无论CPU是否请求单个地址或完整块等于缓存块大小。
因此,如果你问的是32位数字是否在64位机器上的高速缓存中占用了64位空间,那么答案是否定的,它们仍将为自己占用32位。所以一般来说,它会节省一些空间,特别是如果你使用频繁访问的大型数组等。
我个人认为,简单的int
看起来比size_t
简单,大多数编辑都无法识别size_t
类型,因此如果您使用int
语法突出显示也会更好。 ;)
答案 2 :(得分:3)
我正在编码hard spheres model。来源可以在github找到。
我尝试继续使用size_t
作为用作数组索引的变量,并int
使用其他操作,与字大小无关。性能提升显着:执行时间下降~27到24左右。
答案 3 :(得分:0)
这应该是编译器开发人员的决定。
int
是“普通”有符号整数的自然类型。由编译器决定它是什么
如果在特定平台上使用64位整数有一个真正的优势,那么编译器开发人员应该使int
64位。标准允许。
如果编译器开发人员决定坚持使用32位整数,那么通常应该信任他
也许,在极少数情况下,经过大量的优化工作后,您会发现long
效果更好。然后你可能想要改变。