Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

Aligning with new: for a beginner

llevrel
Beginner
1,448 Views

Hi,

I would like to align an array of class instances that's dynamically allocated as follows:

Myclass *foo=new Myclass;

I'll pad the class so that its instances are the size of a cache line. Now I obviously want the array elements to be cache aligned.

How do I achieve this? I'm rather new to C++, so don't be afraid of giving too much detail!

Thanks in advance

0 Kudos
1 Solution
Georg_Z_Intel
Employee
1,401 Views
Hello, there are two basic ways to achieve what you want but with different levels of complexity: 1. Aligning objects usually does make less sense on a high level view. Most likely you have some data members (e.g. arrays) you want to have aligned but not the object itself. For that you can use the __declspcec(align(…)) or __attribute__((aligned(…))) attributes when declaring the data members. Example: [cpp] class A { private: int some_member; __declspec(align(32)) int data[...]; }; [/cpp] 2. If you really know the layout of the object and you want to enforce a certain alignment for the base address of that object, you can use the "placement new" operator. The memory area you pass to it can be allocated with _mm_malloc(...) upfront. _mm_malloc(...) allows to specify the alignment. Or you call standard "malloc" here and enforce correct alignment manually. Best regards, Georg Zitzlsberger

View solution in original post

0 Kudos
31 Replies
Georg_Z_Intel
Employee
1,402 Views
Hello, there are two basic ways to achieve what you want but with different levels of complexity: 1. Aligning objects usually does make less sense on a high level view. Most likely you have some data members (e.g. arrays) you want to have aligned but not the object itself. For that you can use the __declspcec(align(…)) or __attribute__((aligned(…))) attributes when declaring the data members. Example: [cpp] class A { private: int some_member; __declspec(align(32)) int data[...]; }; [/cpp] 2. If you really know the layout of the object and you want to enforce a certain alignment for the base address of that object, you can use the "placement new" operator. The memory area you pass to it can be allocated with _mm_malloc(...) upfront. _mm_malloc(...) allows to specify the alignment. Or you call standard "malloc" here and enforce correct alignment manually. Best regards, Georg Zitzlsberger
0 Kudos
llevrel
Beginner
1,047 Views
Thank you very much (sorry for not responding earlier, for some reason I don't receive email notifications of follow-ups in my subscribed forum threads). Now, suppose I declare: class A { private: __declspec(align(32)) int first_member; double other_member; }; and define: A* array=new A[...]; Will each element array be 32-byte aligned?
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...Will each element array be 32-byte aligned? . I think No. Don't forget that Microsoft compatible C++ compilers have an option /Zp[nn] that sets some alignment for all data types or members of a class / struct. A default value is 8-byte alignment. MSDN also recommends '...You should not use this option unless you have specific alignment requirements...'.
0 Kudos
llevrel
Beginner
1,047 Views
Thanks. I did some tests (using 128-byte alignment instead of 32), and the result is rather strange: elements array are not 128-byte aligned, but are 128-byte spaced! That is, class A has been padded to 128 bytes: long(&(array.first_member))%128 equals 16 for any i. On the other hand, static allocation (A foo[10];) gives the expected result: long(&(array.first_member))%128 equals 0 for any i. Since my goal is avoiding false sharing between array elements, this will do the trick if my class is smaller than 112 bytes (128-16) before padding..
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...That is, class A has been padded to 128 bytes... . That is absolutely expected result and I'm glad to see that static allocation ( on the stack ) resolves the problem. By the way, a C++ operator 'new' allocates a memory block from the heap.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
This is a test with a small C code... . [cpp] void main( void ) { printf("Hello New Edit Control\n"); } [/cpp]
0 Kudos
llevrel
Beginner
1,047 Views
Sergey Kostrov wrote:
I'm glad to see that static allocation ( on the stack ) resolves the problem.
Well, not exactly. Static allocation works as expected in the tests, but it's not an option in my case (I'm not using dynamic allocation for fun ;-) ). However, as I stated, the 16-byte offset introduced by "new" will not harm, as long as my class uses less than 112 bytes.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
Sergey Kostrov wrote:

This is a test with a small C code...
.


void main( void )

{

     printf("Hello New Edit Controln");

}

. A backslash before 'n' in the 'printf' function was deleted. Is it a feature or a bug of the New Edit Control?
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...Well, not exactly. Static allocation works as expected in the tests, but it's not an option in my case... . Did you try to allocate a memory for your data with 'alloca' or '_alloca' CRT-function since it allocates memory on the stack? The function is also very fast.
0 Kudos
llevrel
Beginner
1,047 Views
Sergey Kostrov wrote:
Did you try to allocate a memory for your data with 'alloca' or '_alloca' CRT-function since it allocates memory on the stack? The function is also very fast.
Here I need "long lasting" memory. But thanks anyway for the pointer, I didn't know alloca.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
There is also '_aligned_malloc' CRT-function. Please take a look.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...I need "long lasting" memory... . Do you know that malloc-like CRT-functions ( malloc, calloc, alloca, etc ) could be used to create an instance of a C++ object? However, there is one problem in that case because a constructor won't be called. Let me know if you need some examples on how to do it.
0 Kudos
llevrel
Beginner
1,047 Views
>> some examples on how to do it. Do you mean "how to call the constructor"? Then yes, I'd like an example.
0 Kudos
levicki
Valued Contributor I
1,047 Views
You cannot use __declspec(align) to align dynamically allocated class objects. You need to write placement new and delete operators which will allocate and free aligned memory. Search the forum, I have already explained it and gave examples long time ago.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...Do you mean "how to call the constructor"? Then yes, I'd like an example. . I don't call a C++ object constructor explicitly. I call a special method of the class that simulates a constructor. I'll post an example later. . Best regards, Sergey
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>...You need to write placement new and delete operators which will allocate and free aligned memory... . I did a quick investigation and I see that a C++ operator '::operator new( nSize )' has to be called in order to construct an object properly ( with Virtual Table initialized ). Usually it looks like: . [cpp] ... void * PASCAL CSomeObject::operator new( size_t nSize ) { return ::operator new( nSize ); } ... [/cpp] . and if you replace it with: . [cpp] ... void * PASCAL CSomeObject::operator new( size_t nSize ) { return ::alligned_malloc( nSize ); } ... [/cpp] . an object won't be constructed completely and Virtual Table wont' be initialized.
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
>>>>...Do you mean "how to call the constructor"? Then yes, I'd like an example. >>. >>I don't call a C++ object constructor explicitly. I call a special method of the class that simulates a constructor. I'll post an example later. . [cpp] class CSomeObject { public: CSomeObject() { Init(); }; ~CSomeObject(){}; void Init(){}; }; ... void main( void ) { CSomeObject *pSO = NULL; pSO = ( CSomeObject * )malloc( sizeof( CSomeObject ) ); pSO->Init(); if( pSO != NULL ) { free( pSO ); pSO = NULL; } } [/cpp] . Take into account that the method of creating / deleting a C++ object with CRT-fuctions 'malloc' / 'free' has lots of limitations. It has to be used in a very simple cases when the C++ object is simple and doesn't have any virtual functions ( including a virtual destructor ). However, it is a very fast way to create thousands of small objects when there are time constraints ( for example in a real-time environment ).
0 Kudos
SergeyKostrov
Valued Contributor II
1,047 Views
Why does the new editor add extra lines when I "embedd" C++ codes? Take a look at previous post at lines 2, 4, 6, etc, in my C++ example. Also, the editor changes a font to a smaller one.
0 Kudos
levicki
Valued Contributor I
1,047 Views
As i said, write placement new and delete operators and your constructors and destructors will work. Sergey, you are confusing him with unnecessary complexity which does not solve the problem properly. Placement new is described on wikipedia, just google for it.
0 Kudos
SergeyKostrov
Valued Contributor II
869 Views
>>...I would like to align an array of class instances that's dynamically allocated as follows: >> >>Myclass *foo=new Myclass; . Why wouldn't you consider an array of aligned pointers to objects of Myclass? Here is a pseudo-codes: . [cpp] ... class Myclass { public: Myclass(){}; ~Myclass(){}; }; ... align( some boundary ) Myclass *pFoo[ NumberOfElements ] = { NULL }; . for( i = 0; i < NumberOfElements; i+=1 ) { pFoo = ( Myclass * )new Myclass(); } [/cpp]
0 Kudos
Reply