When people are trying to perform rigorous benchmarks in various libraries, I sometimes see code like this:
auto std_start = std::chrono::steady_clock::now();
for (int i = 0; i < 10000; ++i)
for (int j = 0; j < 10000; ++j)
volatile const auto __attribute__((unused)) c = std_set.count(i + j);
auto std_stop = std::chrono::steady_clock::now();
The volatile
is used here to prevent the optimizer from noticing that the result of the code under test is discarded, and then discarding the entire computation.
When the code under test doesn't return a value, say it is void do_something(int)
, then sometimes I see code like this:
auto std_start = std::chrono::steady_clock::now();
for (int i = 0; i < 10000; ++i)
for (int j = 0; j < 10000; ++j)
static_cast<volatile void> (do_something(i + j));
auto std_stop = std::chrono::steady_clock::now();
Is this correct usage of volatile
? What is volatile void
? What does it mean from the point of view of the compiler and the standard?
In the standard (N4296) at [dcl.type.cv]
it says:
7 [ Note: volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might be changed by means undetectable by an implementation. Furthermore, for some implementations, volatile might indicate that special hardware instructions are required to access the object. See 1.9 for detailed semantics. In general, the semantics of volatile are intended to be the same in C ++ as they are in C. — end note ]
In section 1.9 it specifies a lot of guidance about the execution model, but as far as volatile is concerned, it's about "accessing a volatile
object". It's not clear to me what executing a statement that has been casted to volatile void
means, assuming I understand the code correctly, and exactly what if any optimization barrier is produced.