Skip to main content
GameDev.net gamedev.net
🔒 Locked

aligned new class array operator

Started by TerrorFLOP Jan 23, 2007 at 11:58 AM 3 replies 3.3k views
Original Post
TerrorFLOP
TerrorFLOP
I've written a macro which is used in class declarations, which simply defines a static new operator method. However, it's a bit messy as its signature looks a bit like this: Class CClass { public: // public constructors, destructors and methods etc ALIGN_OPERATOR_NEW // macro which defines the new operator }; const int CACHE_LINE = 32; // align heap class arrays on the 32 bit cache line. const int SIZE = 10; // size of the array. CClass *pClass = new (CACHE_LINE, SIZE) CClass [SIZE]; As you can see I had to make use of the SIZE constant twice. Messy yes! The reason? Well, during runtime, the Visual C++ Express 2005 complier seems to produce code that allocates extra bytes during a call to new. Even custom made new operators. I assume this is down to the virtual pointer (dependent upon the class of course) as well as for various other house-keeping duties in order to properly de-allocate the array during a subsequent delete [] call. Hence, I don't quite get perfectly aligned class arrays on the heap. Even when I use the _aligned_offset_malloc function. (Or was it _align_offset_malloc? I'm not on my home computer here!) Anyway, I've introduce the SIZE argument into the new operator, so that I can perform a simple operation which allows me to align the class array on the heap properly. I would sure appreciate it if someone could tell me if there's a neater way of doing this. Or if they could tell me what exactly goes on behind the scenes during runtime, when complex classes are allocated on the heap using operator new.
jpetrie
jpetrie
Could you explain why you're trying to do this? Aligned objects can be a pain and there are some situations where you're just going to be stuck.

Quote:
the Visual C++ Express 2005 complier seems to produce code that allocates extra bytes during a call to new. Even custom made new operators.

Of course. This is always the case (the runtime needs to allocate extra space to store bookkeeping information, and so does the OS, et cetera -- depending on the methods you're using to interrogate memory usage, you may or may not be seeing those). The size of the class may not be what you're expecting just by examination of the class's definition, as well -- it might have a vtable pointer, it might have padding or alignment bytes inserted by the compiler based on #pragma settings, et cetera.

If you can provide more information about the sizes you're expecting, the sizes you're seeing, and how you're seeing those numbers and any alignment/packing #pragmas you have in effect, that would be helpful.

You also need to make sure that the actual size of the class is actually alignable to the boundary you want, otherwise when you make an array the elements other than the first might be unaligned (since arrays are contiguous).

What does your macro expand to and how is your custom new implemented? Have you looked into __declspec(align) and such?
TerrorFLOP
TerrorFLOP
Well, the code I wrote works. I just wanted to see if there was a better, neater way.

I understand about the __declspec(align) directive. I use that to make sure stack objects get aligned properly. But did you know that is not necessarily the case for heap allocated objects. Even if they have been declared with __declspec(align) in place?

I did read a little on the #pragmas... I assume you mean switching it on so that objects are aligned automatically, but again, only stack based objects seemed to be affected.

Integral types or simple structures align no problem on the heap or stack using these methods, but more complex objects don't seem to align properly in a heap based array.

The only way is to call _aligned_malloc for the number of object elements you want on the heap. The problem with that approach, is that object default constructors don't get called and then you're left with initializing each object element yourself!

Why do I need to have aligned heap based objects anyway? Well, for time-critical applications, important objects that are aligned to the cache line are fetched a little quicker (with less catch misses). And I wanted to have the advantage of having variable arrays of these objects on the runtime heap.

So this is all just another glorified exercise to gain yet more CPU cycles in my projects. Anyway, thanks for the response. I guess aligned class array heap allocations are a bit more tricky than I first suspected LOL!

Note: If you still wish to see my code anyway, then give me a holla and I'll submit it next time... No problemo!

[Edited by - TerrorFLOP on January 24, 2007 4:07:10 AM]
jpetrie
jpetrie
Quote:

But did you know that is not necessarily the case for heap allocated objects. Even if they have been declared with __declspec(align) in place?


I did, and that's one of the issues I've been hinting at. Sometimes it isn't possible to perform the alignment and have an array, because arrays must be contiguously allocated. If they are not, you couldn't index into the array!

(Padding within the object counts as part of the object, so doesn't affect your ability to index the array; however padding external to the object that would be required to align objects that aren't naturally alignable to a particularly boundary in an array is not part of the object and would consequently break the indexing operation because the amount of that padding isn't necessarily constant).

Quote:

Why do I need to have aligned heap based objects anyway? Well, for time-critical applications, important objects that are aligned to the cache line are fetched a little quicker (with less catch misses). And I wanted to have the advantage of having variable arrays of these objects on the runtime heap.


Have you profiled and actually determined this is an issue? I have my doubts, because if it were it would be an issue on a very small subset of objects so you wouldn't need such a general purpose solution. In general I don't think the performance gains are worth worrying about, especially given the effort.

Quote:

Note: If you still wish to see my code anyway, then give me a holla and I'll submit it next time... No problemo!

Post it, if you want, and I can tell you why your objects aren't being aligned.
ajas95
ajas95
Hi, this page may be helpful to you. Particularly:

"The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is greater."

This leads me to believe that by declspec(align())ing your class will change its size, so as to be a multiple of your alignment... which should make your array sizing work implicitly.

As far as reasons why a structure is not an expected size... you know that vtable may not be 4 bytes (in cases of multiple virtual inheritance, for instance), and that if RTTI is turned on, that will get some bytes too. I suspect RTTI may well be your problem.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.