views:

124

answers:

3

I want to have a base class which dictates the alignment of the objects which inherit from it. This works fine for the heap because I can control how that gets allocated, and how arrays of it get allocated in a custom array template. However, the actual size of the class as far as C++ is concerned doesn't change at all. Which is to say if I perform pointer arithmetic on a pointer of the derived class then it will skip to the wrong location. That's issue one.

Issue two is stack alignment. There doesn't seem to be a way to directly force the entire stack to be 16 byte aligned pointers.

The only thing I can see to affect these at all is the vc++ and g++ compiler specific settings, but the problem here is I don't want to have to manually fix the alignment all the time. That would be bound to be error prone, not to mention a pain.

I could also maybe make some kind of smart pointer but that would introduce more issues, too.

If I just align the base class, will the child classes be aligned, as well? If so, that would solve most of my problems but that seems doubtful to be the case (though I will try this).

A: 

If a base class has a particular alignment requirement, then any derived classes will have at least that alignment (they could get a stricter alignment requirement due to their own members). Otherwise the compiler couldn't guarantee that accessing the base members would meet the requirements they have.

However, there's really nothing you can portably do for stack alignment - that's handled entirely by the compiler and the compiler's platform ABI requirements. As you indicate, a compiler option or maybe a pragma might let you exert some control, but nothing portable.

Michael Burr
Thanks, that helps. Is there some way to avoid the compiler errors I get when I try to assign it to an 'unaligned' pointer? I know it's always aligned since I get it myself. I'd rather avoid putting these declarations through the whole program, if possible. It seems like this should be easy but it is not.
Charles Eli Cheese
Nevermind, I finally get the issue. I had this pop up before and didn't think it could be resolved, but just changing to passing a reference fixed it. I have been very confused, but I guess it's a confusing topic.
Charles Eli Cheese
You might want to post some code - I'm not sure what you're compiler might be complaining about with the 'unaligned pointer'. If you're casting a pointer to a byte array to your class you might be violating alignment requirements. Whatever you're doing with a reference might be hiding a problem.
Michael Burr
A: 

Keeping the Michael's answer in mind with respect to portability.. I assume you are aiming at SSE vectorization and are starting to feel that pain and that really ought to be a standard way to do it with explicit hints and low-level control. Both compilers you mention do strive for 16 byte alignment on stack by default.

So while compiler support does vary, can be changed, is challenged etc, it can also be heavily underutilised on one of them; it depends on the optimizers and types you are containing and naturally the vectorizer choices for sanity. Then again, it's not clear what you are doing and what the use is.

Since your problem definition without an example is sketchy, perhaps you can give a shot to declspec(align(16)) for California (with LTCG), and __attribute((aligned (16))) for gcc. If that helps, it'd be good to let us know and what specifically worked or not in example, which compiler warnings or errors too. I would also avoid any smart pointer usage for various reasons.

sizeof being in your question indicates you are also facing challenges with regards to variable arrays and pointer types, in which case the former might be problematic. And even though you can live with losing the copy constructor and assignment facilities, it will do no harm to inspect the machine code. That is, in case of complication, what you need to do is look at the output and in case of VC++ switch to Intel for better hints in Windows, and test for/compilet and runtime assert/trap failures early or for the other one pick any free object file analysis tool. Then you just work around the clearly problematic constructs in a sanest way you can, something that is always possible.

rama-jka toti
I see now why it's doing it. I am not sure how well it keeps to 16 bytes but even the possibility causes compiler error for pass by value. I am not sure why, but those passes were just a mistake anyway. Thanks for the good answers, guys, I was mostly overcomplicating but works like a charm now. Amazing speed improvements.
Charles Eli Cheese
A: 

We had a similar problem on PARISC HPUX where the only atomic construct was a 4 byte atomic clear that required 16 byte alignment.

We could fudge it by declaring our 4 byte quantity like so:

struct Stupid_HPUX
{
   int 4byteLockWordInHere[4] ;
} ;

and picking the right one to use at runtime. For your problem, you could do something similar

union rawMemory
{
   int blah[(sizeof(yourtype) + 16)/4] ;
   char c[1] ;
} u ;

then use placement new with a runtime determined address to fix the location required.

Peeter Joot