Vit*_*meo 20 c++ optimization unions language-lawyer c++17
假设您必须实现一个static_vector<T, N>类,它是一个完全存在于堆栈中并且永远不会分配的固定容量容器,并且公开std::vector类似接口.(Boost提供boost::static_vector.)
考虑到我们必须为最大实例提供未初始化的存储,在设计内部数据布局时可以有多种选择:NT
单一成员union:
union U { T _x; };
std::array<U, N> _data;
Run Code Online (Sandbox Code Playgroud)单身std::aligned_storage_t:
std::aligned_storage_t<sizeof(T) * N, alignof(T)> _data;
Run Code Online (Sandbox Code Playgroud)数组std::aligned_storage_t:
using storage = std::aligned_storage_t<sizeof(T), alignof(T)>;
std::array<storage, N> _data;
Run Code Online (Sandbox Code Playgroud)无论选择如何,创建成员都需要使用"放置new",访问它们将需要一些东西reinterpret_cast.
现在假设我们有两个非常小的实现static_vector<T, N>:
with_union:使用"单一成员union"方法实施;
with_storage:使用"单一std::aligned_storage_t"方法实施.
让我们使用both g++和clang++with 执行以下基准测试-O3.我使用quick-bench.com完成这项任务:
void escape(void* p) { asm volatile("" : : "g"(p) : "memory"); }
void clobber() { asm volatile("" : : : "memory"); }
template <typename Vector>
void test()
{
for(std::size_t j = 0; j < 10; ++j)
{
clobber();
Vector v;
for(int i = 0; i < 123456; ++i) v.emplace_back(i);
escape(&v);
}
}
Run Code Online (Sandbox Code Playgroud)
(escape和clobber从钱德勒卡鲁斯的CppCon 2015年采取的谈话:"调整C++:基准,并且CPU和编译器哦,我的!")
g++ 7.2 (住在这里):clang++ 5.0 (住在这里):从结果中可以看出,g++似乎能够积极地优化(矢量化)使用"单一std::aligned_storage_t"方法的实现,而不是使用的实现union.
我的问题是:
标准中是否存在任何阻止实施使用的union积极优化? (即标准在使用时为编译器授予更多自由std::aligned_storage_t- 如果是,为什么?)
这纯粹是"实施质量"问题吗?
Bar*_*rry 11
xskxzr是对的,这个问题与此问题相同.从根本上说,gcc错失了一个忘记std::array数据一致的优化机会.John Zwinck帮助报告了错误80561.
您可以通过对以下两项更改中的一项进行验证来验证此基准with_union:
改变_data从std::array<U, N>简单一个U[N].性能变得相同
_data通过将实现更改emplace_back()为:提醒实际对齐的gcc :
template <typename... Ts>
T& emplace_back(Ts&&... xs)
{
U* data = static_cast<U*>(__builtin_assume_aligned(_data.data(), alignof(U)));
T* ptr = &data[_size++]._x;
return *(new (ptr) T{std::forward<Ts>(xs)...});
}
Run Code Online (Sandbox Code Playgroud)无论是与你的标杆,其余的变化让我之间比较的结果WithUnion和WithAlignedStorage.
| 归档时间: |
|
| 查看次数: |
471 次 |
| 最近记录: |