10

我想知道在 64 位程序上继续使用int(在 x86 和 x86_64 上都是 32 位)对于没有什么特别的并且不需要跨越 2^64 的变量(例如迭代计数器)是否是一个好主意,或者如果最好使用size_t与 CPU 的字长匹配的。

如果你继续使用int你可以节省一半的内存,这可能意味着关于 CPU 缓存的事情,但我不知道在 64 位机器上是否每个 32 位数字都必须在任何使用之前扩展到 64 位。

编辑:我已经用我的程序进行了一些测试(请参阅自我答案,我仍然保持 janneb 被接受,因为它很好)。事实证明,有显着的性能改进。

4

4 回答 4

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 需要更多的内存;如果你有这样的数组,它肯定会影响性能,而不是避免零/符号扩展的相对较小的好处。如果不确定,请配置文件!

于 2012-06-06T10:28:56.570 回答
3

我正在编写一个小硬球模型。源代码可以在github上找到。

我试图继续使用size_t用作数组索引的变量,以及int我在哪里执行与字长无关的其他操作。性能提升非常显着:大约 27 到 24 次执行时间下降。

于 2012-06-08T11:06:44.990 回答
3

在Cache方面,会节省空间;缓存处理数据块,无论 CPU 是否请求单个地址或等于缓存块大小的完整块。

因此,如果您询问 32 位数字是否在 64 位机器上的缓存内占用 64 位空间,那么答案是否定的,它们仍然会占用 32 位。所以总的来说,它会为你节省一些空间,特别是如果你使用的是频繁访问的大型数组等。

在我个人看来,简单int看起来比size_t大多数编辑器都无法识别size_t类型,因此如果您使用int. ;)

于 2012-06-06T10:27:48.543 回答
0

This should be the compiler developer's decision.

int is the natural type for "normal" signed integers. It's up to the compiler to decide what it is.
If, on a specific platform, there's a real advantage in using 64bit integers, the compiler developer is expected to make int 64bit. The standard allows it.

If the compiler developer decided to stick with 32bit integers, you should normally trust him.
Maybe, in some rare cases, after a significant optimization effort, you'll find that long works better. Then you might want to change.

于 2012-06-06T13:38:10.960 回答