views:

405

answers:

2

I am working on lock free structure with g++ compiler. It seems that with -o1 switch, g++ will change the execution order of my code. How can I forbid g++'s optimization on certain part of my code while maintain the optimization to other part? I know I can split it to two files and link them, but it looks ugly.

+3  A: 

You can use a function attribute "__attribute__ ((optimize 0))" to set the optimization for a single funtion, or "#pragma GCC optimize" for a block of code. These are only for GCC 4.4, though, I think - check your GCC manual. If they aren't supported, separation of the source is your only option.

I would also say, though, that if your code fails with optimization turned on, it is most likely that your code is just wrong, especially as you're trying to do something that is fundamentally very difficult. The processor will potentially perform reordering on your code (within the limits of sequential consistency) so any re-ordering that you're getting with GCC could potentially occur anyway.

DavidK
+3  A: 

If you find that gcc changes the order of execution in your code, you should consider using a memory barrier. Just don't assume that volatile variables will protect you from that issue. They will only make sure that in a single thread, the behavior is what the language guarantees, and will always read variables from their memory location to account for changes "invisible" to the executing code. (e.g changes to a variable done by a signal handler).

GCC supports OpenMP since version 4.2. You can use it to create a memory barrier with a special #pragma directive.

A very good insight about locking free code is this PDF by Herb Sutter and Andrei Alexandrescu: C++ and the Perils of Double-Checked Locking

Johannes Schaub - litb
Great link, I really enjoyed that article.
Tom Leys
volatile variables *could* solve the problem depending on the specifics of the issue. They'll guaranteed ordered access respective to one another, but without respect for non-volatile data. Memory barriers are the answer, but is there a platform independent way to create one in GCC? I think that gcc regards inline assembly blocks with "m" specified in the clobber list as full barriers, but other than this I don't know.
Dan Olson
right, i was being blurry in my answer. it will not reorder volatile reads/writes with respect to other volatile reads/writes in the same thread. not across thread boundaries. I'll edit to be clearer
Johannes Schaub - litb
GCC has builtin functions which can create fences that serve that purpose, i believe. i will read about them and add it.
Johannes Schaub - litb
Thanks for updating even though this is ancient, I think this is the right URL: http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html#Atomic-Builtins but there's still some sketchiness. C++0x will solve everything though.... I hope!
Dan Olson
watched the videos again today and will see how i can change my answer to reflect the new things. Yeah the __sync things are the way to do. Inserting fences at proper place. C++1x will have those too, also having atomic<T> types. watch this vid for more: http://www.youtube.com/watch?v=mrvAqvtWYb4
Johannes Schaub - litb