Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are float arrays always aligned to 16 byte boundaries?

My understanding is that you have to explicitly specify the alignment of an array, if you want it aligned.

However, the float arrays I declare always seem to be aligned to 16 byte.

float *ptr1 = new float[1];
cout<<"ptr1: "<<ptr1<<endl;
float *ptr2 = new float[3];
cout<<"ptr2: "<<ptr2<<endl;
float arr1[7];
cout<<"arr1: "<<arr1<<endl;
float arr2[9] __attribute__((aligned(2)));
cout<<"arr2: "<<arr2<<endl;

Here is the output

ptr1: 0x13dc010
ptr2: 0x13dc030
arr1: 0x7fff874885c0
arr2: 0x7fff87488590

Is there a reason for this? I am using gcc 4.6.3

However if it's a pointer to a float location or statically allocated, I don't see it

static float arr3[9] __attribute__((aligned(2)));
cout<<"arr3: "<<arr3<<endl;
float *x;
cout<<"x: "<<x<<endl;

Output:

arr3: 0x4030b2
x: 0x7fff8c7dd9e8

This code was run on x64.

like image 590
Mathai Avatar asked Feb 14 '23 14:02

Mathai


1 Answers

Alignment requirements are determined by each compiler, influenced by hardware requirements and any relevant ABI.

The C and C++ languages discuss alignment for types, but they don't impose any specific requirements (except that, for example, a structure's alignment is at least the alignment of any of its members). A valid implementation could permit all data types to be byte aligned, or it could require each scalar type to be aligned to its own size (the latter is more common). Intermediate alignments are possible, such as aligning 8-byte types on 4-byte boundaries.

On the x86 in particular, aligning scalars to their size makes for more efficient access, but misaligned accesses still work correctly, though a little more slowly.

The required alignment for an array of float is the same as the required alignment for a single float object. If float is 4 bytes, then that alignment can be no greater than 4 bytes, since arrays do not have gaps between their elements.

A particular compiler might choose to impose stricter alignment on array objects, as you've (probably) seen, if it makes access to those objects a little more efficient.

And if the new operator is implemented by calling malloc, then all new-allocated objects will have an alignment strict enough for any type.

If float arrays are always aligned to 16-byte boundaries, it's because your compiler chooses to do allocate them that way, not because it's required by the language. On the other hand, if you use aliasing to force a float array to a 4-byte alignment (assuming sizeof (float) == 4), then accesses to that array and to its elements should still work correctly.

Incidentally, when I run your code (after wrapping it in a main program) on my x86_64 system, I get results similar to yours. When I run it on an x86 system, I get:

ptr1: 0x9e34008
ptr2: 0x9e34018
arr1: 0xbfefa160
arr2: 0xbfefa17c

I'm using gcc under Linux on both systems.

So the straightforward answer to your question is no, float arrays are not always aligned to 16-byte boundaries.

But in most cases there's no particular reason for you to care. Unless you play aliasing tricks (treating an object of some declared type as if it were of another type), the compiler will always give each object at least the alignment it needs for correct access.

like image 83
Keith Thompson Avatar answered Feb 20 '23 04:02

Keith Thompson