views:

2169

answers:

5

Intel's 32-bit processors such as Pentium have 64-bit wide data bus and therefore fetch 8 bytes per access. Based on this, I'm assuming that the physical addresses that these processors emit on the address bus are always multiples of 8.

Firstly, is this conclusion correct?

Secondly, if it is correct, then one should align data structure members on an 8 byte boundary. But I've seen people using a 4-byte alignment instead on these processors.

How can they be justified in doing so?

+4  A: 

Physical bus is 64bit wide ...multiple of 8 --> yes

HOWEVER, there are two more factor to consider:

  1. Some x86 instruction set are byte addressed. Some are 32bit aligned (that's why you have 4 byte thing). But no (core) instruction are 64bits aligned. The CPU can handle misaligned data access.
  2. If you care about the performance, you should think about the cache line, not main memory. Cache lines are much wider.
J-16 SDiZ
I don't understand. You agree that processors like the Pentium place only multiples 8 on the address bus. Then you say 4-byte alignment is okay. Well, consider the address 0x000044444. Although it is 4-byte aligned, the processor is never going to emit this address on the address line because it's not a multiple of 8. Hence, fetching memory at this address will require two fetches. How is then 4-byte alignment justified?
Frederick
Why would it require two fetches? It would simply request all the data from 0x000044440 to 0x000044447, and since we're interested in 0x000044444-0x000044447, what's the problem?
jalf
Why are talking about instructions alignment, that makes no sense. Padding instructions to some boundary with NOPs achieves nothing.
mP
A: 

For random access and as long as the data is not misaligned (e.g. crossing a boundary), I don't think that it matters much; the correct address and offset in the data can be found with a simple AND construct in hardware. It gets slow when one read access is not sufficient to get one value. That's also why compilers usually put small values (bytes etc.) together because they don't have to be at a specific offset; shorts should be on even addresses, 32-bit on 4-byte addresses and 64-bit on 8-byte addresses.

Note that if you have caching involed and linear data access, things will be different.

Lucero
+2  A: 

The usual rule of thumb (straight from Intels and AMD's optimization manuals) is that every data type should be aligned by its own size. An int should be aligned on a 32-bit boundary, a long long on a 64-bit boundary, and so on. A char will fit just fine anywhere.

Another rule of thumb is, of course "the compiler has been told about alignment requirements". You don't need to worry about it because the compiler knows to add the right padding and offsets to allow efficient access to data.

The only exception is when working with SIMD instructions, where you have to manually ensure alignment on most compilers.

Secondly, if it is correct, then one should align data structure members on an 8 byte boundary. But I've seen people using a 4-byte alignment instead on these processors.

I don't see how that makes a difference. The CPU can simply issue a read for the 64-bit block that contains those 4 bytes. That means it either gets 4 extra bytes before the requested data, or after it. But in both cases, it only takes a single read. 32-bit alignment of 32-bit-wide data ensures that it won't cross a 64-bit boundary.

jalf
Not if the 4 bytes straddle one 64 bit chunk over to the next.
mP
how would that happen if it is aligned on a 4-byte boundary?
jalf
I can't believe I missed this simple reasoning. Why waste 4 extra bytes in 8-byte alignment when you achieve the same performance with 4 byte? Thanks Jalf. You make perfect sense.
Frederick
+1  A: 

They are justified in doing so because changing to 8-byte alignment would constitute an ABI change, and the marginal performance improvement is not worth the trouble.

As someone else already said, cachelines matter. All accesses on the actual memory bus are in terms of cache lines (64 bytes on x86, IIRC). See the "What every programmer needs to know about memory" doc that was mentioned already. So the actual memory traffic is 64 byte aligned.

janneb
A: 

The 64 bits bus you refer to feeds the caches. As a CPU, always read and write entire cache lines. The size of a cache line is always a multiple of 8, and its physical address is indeed aligned at 8 byte offsets.

Cache-to-register transfers do not use the external databus, so the width of that bus is irrelevant.

MSalters