Pas*_* By 1 c++ volatile c++11
我是C++的新手,最近我遇到了一些关于变量意味着什么的信息volatile.据我所知,这意味着对变量的读取或写入永远不会被优化.
然而,当我声明一个volatile不是1,2,4,8字节大的变量时会出现一种奇怪的情况:编译器(启用了C++ 11的gnu)似乎忽略了volatile说明符
#define expand1 a, a, a, a, a, a, a, a, a, a
#define expand2 // ten expand1 here, expand3 to expand5 follows
// expand5 is the equivalent of 1e+005 a, a, ....
struct threeBytes { char x, y, z; };
struct fourBytes { char w, x, y, z; };
int main()
{
// requires ~1.5sec
foo<int>();
// doesn't take time
foo<threeBytes>();
// requires ~1.5sec
foo<fourBytes>();
}
template<typename T>
void foo()
{
volatile T a;
// With my setup, the loop does take time and isn't optimized out
clock_t start = clock();
for(int i = 0; i < 100000; i++);
clock_t end = clock();
int interval = end - start;
start = clock();
for(int i = 0; i < 100000; i++) expand5;
end = clock();
cout << end - start - interval << endl;
}
Run Code Online (Sandbox Code Playgroud)
他们的时间是
foo<int>():~1.5sfoo<threeBytes>():0我用不同的变量(用户定义与否)测试了1到8个字节,只有1,2,4,8需要时间来运行.这是一个只存在于我的设置中的错误,还是volatile对编译器的请求,而不是绝对的东西?
PS四字节版本总是占用其他时间的一半,也是混乱的来源
结构版本可能会被优化,因为编译器意识到没有副作用(没有读取或写入变量a),无论如何volatile.你基本上有一个无操作,a;所以编译器可以做任何你喜欢的事情; 它不是被迫展开循环或优化它,所以这volatile并不重要.在ints 的情况下,似乎没有优化,但这与以下用例一致volatile:只有在循环中有可能"访问对象"(即读取或写入)时,才应该期望非优化.然而,构成"访问对象"的内容是实现定义的(尽管大部分时间它遵循常识),请参见底部的编辑3.
这里的玩具示例:
#include <iostream>
#include <chrono>
int main()
{
volatile int a = 0;
const std::size_t N = 100000000;
// side effects, never optimized
auto start = std::chrono::steady_clock::now();
for (std::size_t i = 0 ; i < N; ++i)
++a; // side effect (write)
auto end = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< " ms" << std::endl;
// no side effects, may or may not be optimized out
start = std::chrono::steady_clock::now();
for (std::size_t i = 0 ; i < N; ++i)
a; // no side effect, this is a no-op
end = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
<< " ms" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
编辑
对于标量类型,no-op实际上并未实现优化,正如您在此最小示例中所看到的那样.对于struct的,虽然,它被优化掉了.在我链接的示例中,clang没有优化代码而没有优化,但优化了两个循环-O3.gcc没有优化就不会优化循环,但只优化第一个循环并进行优化.
编辑2
clang吐出警告:warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue].所以我最初的猜测是正确的,编译器可以优化no-ops,但它不是强制的.为什么它为structs而不是标量类型是我不理解的东西,但它是编译器的选择,并且它是标准兼容的.由于某种原因,只有在no-op为a时它才会发出此警告struct,并且当它是标量类型时不会发出警告.
还要注意,你没有"读/写",你只有一个无操作,所以你不应该期待任何东西volatile.
编辑3
来自金书(C++标准)
7.1.6.1/8 cv-qualifiers [dcl.type.cv]
什么构成对具有volatile限定类型的对象的访问是实现定义的....
因此,编译器需要决定何时优化循环.在大多数情况下,它遵循常识:读取或写入对象时.
| 归档时间: |
|
| 查看次数: |
334 次 |
| 最近记录: |