10

I wonder if it's a good idea to keep using int (which is 32 bit on both x86 and x86_64) on 64 bit programs for variables that have nothing special and do not really need to span up to 2^64, like iteration counters, or if it's better to use size_t which matches the word size of the CPU.

For sure if you keep using int you save half of the memory, and that could mean something speaking about CPU cache, but I don't know then if on 64 bit machine every 32 bit number has to be extended to 64 bit before any use.

EDIT: I've ran some test with a program of mine (see the self answer, I still keep janneb's as accepted though because it is good). It turns out that there is a significant performance improvement.

6
  • 1
    Iteration counters should not be in the CPU cache; they should reside in registers. Commented Jun 6, 2012 at 10:16
  • 1. I believe the compilers automatically fix a lot of such things for you. 2. Why don't you write a program testing the performance between the two? Commented Jun 6, 2012 at 10:17
  • sure, but "but I don't know then if on 64 bit machine every 32 bit number has to be extended to 64 bit before any use". And that was just an example. Commented Jun 6, 2012 at 10:18
  • 2
    You should look at the design of the x86_64 instruction set, and you would see that no, not only 32-bit registers do not have to be extended to 64-bit to be operated on, but in fact, the 64-bit instructions are typically one byte longer (they always require a prefix. Their 32-bit counterparts do not require the prefix when they operate on the first half of the registers). Commented Jun 6, 2012 at 10:18
  • @Shahbaz sure I'll do so, I've already discovered interesting stuff (long double being way faster than double for example). But I'd love to have some theoretical explanation, and maybe save 1 hour of testing. Commented Jun 6, 2012 at 10:19

4 Answers 4

4

For array indices and pointer arithmetic, types which are of the same size as a pointer (typically, size_t and ptrdiff_t) can be better, as they avoid the need to zero or sign extend the register. Consider

 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]; } 

With GCC 4.4 -O2 on x86_64 the following asm is generated:

 .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 

As can be seen, the versions with the int and unsigned int index (onei and oneu) requires an extra instruction (movslq/mov) to sign/zero extend the register.

As was mentioned in a comment, the downside is that encoding a 64-bit register takes more space than the 32-bit part, bloating the code size. Secondly, ptrdiff_t/size_t variables need more memory than the equivalent int; if you have such arrays it can certainly affect performance much more than the relatively small benefit of avoiding the zero/sign extension. If unsure, profile!

Sign up to request clarification or add additional context in comments.

Comments

3

In terms of Cache, it will save space; cache handles blocks of data, regardless of whether CPU requested a single address or the complete chunk equal to cache block size.

So if you are asking whether 32-bit numbers take 64-bits of space inside caches on 64 bit machines then the answer is no, they will still take 32 bits for themselves. So in general, it will save you some space, especially if you are using large arrays with frequent accesses etc.

In my personal opinion, a simple int looks simpler than size_t and most editors will not recognize size_t type so syntax highlighting will also be better if you use int. ;)

3 Comments

I'd suggest you stop using any editor that doesn't recognize size_t immediately!
Certainly stop using an editor that doesn't let you configure what's highlighted as a type :-)
on windows, many editors (MS Visual Studio, ultra edit, notepad++, editplus) do not recognize size_t. if one develops on Unix/Linux environments then its safe, otherwise, well still safe just a bit more messed up :P anyways, this wasn't the major point.. :)
3

I am coding a little hard spheres model. The source can be found on github.

I tried to keep using size_t for variables that are used as index of arrays, and int where I do other operations, not related to word size. The performance improvement was significant: a ~27 to ~24 execution time drop.

1 Comment

very good real-world example that demonstrates the problem in the first place. +1
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.

1 Comment

Are you sure? I’ve read elsewhere that compilers need to conform to platform standards, whose decisions are influenced by backward compatibility: unix.org/whitepapers/64bit.html

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.