Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ volatile and operator overloading for CUDA application

I have a class A that I overload its operator=. However it is required that I need to do something like this:

volatile A x;
A y;
x = y;

which raised an error while compiling

error: no operator "=" matches these operands
       operand types are: volatile A = A

If I removed volatile, it's compilable. Is there anyway to have this compiled without removing the "volatile" (and still keep the behavior of volatile) ?


Basically this is a CUDA program in which 'x' is a shared memory ( all threads can access and modify its value ). I want it to be "volatile" in order to avoid the compiler optimization and re-use the value instead of accessing the memory address.

More on the problem: at the beginning A is just a primitive type e.g integer, volatile worked as expected and doesn't cause any problem, now I want it to be a custom class ( integer 128-bit for example ). I'm not sure why C++ complain in this case but not with primitive data type.

Thanks in advance.

like image 227
w00d Avatar asked Sep 13 '10 09:09

w00d


4 Answers

Assuming the volatile qualification is necessary, you'll have to add a volatile assignment operator to A (A& A::operator=(const A&) volatile).

const_cast<A&>(x) = y will make it compile, but will technically cause undefined behaviour, and will certainly remove the guarantees that volatile gives.

like image 95
Mike Seymour Avatar answered Oct 19 '22 17:10

Mike Seymour


The "volatile isn't a lot of use in C++ threading" comment is irrelevant to the question, which is CUDA-specific. volatile is needed for warp synchronous coding in CUDA.

like image 43
ArchaeaSoftware Avatar answered Oct 19 '22 18:10

ArchaeaSoftware


volatile isn't a lot of use in C++ threading (see Dave Butenhof's explanation at http://www.lambdacs.com/cpt/FAQ.html#Q56). It's not sufficient to ensure your program flushes the data written out of core-local cache to a point where other programs can see the updates in shared memory, and given almost everyone's multi-core these days, that's a serious problem. I suggest you use proper threading synchronisation methods, such as boost's if your portability needs match it, or perhaps POSIX mutexes and condition variables, failing that more architecture dependent techniques like memory barriers or atomic operations that implicitly sync memory between cores.

I'm sure you want it to be fast, but fast and unstable isn't generally as useful as slow and reliable, especially if you ship a product that's only unstable on your customer's hardware.

like image 1
Tony Delroy Avatar answered Oct 19 '22 17:10

Tony Delroy


Declaring a copy constructor

volatile A& operator=(volatile A&) volatile;

worked for me with nvcc. Note that you may have to pass around the non-primitive type by reference only. Else you'll need more copy-constructors that convert volatile instances to non-volatile whenever the non-primitive type is passed by value to a non-volatile parameter. It really boils down to establishing volatile-correctness (much like const-correctness).

like image 1
jascha Avatar answered Oct 19 '22 17:10

jascha