【发布时间】:2020-10-10 19:42:41
【问题描述】:
我刚刚了解了 alignof 和 alignas C++ 关键字,但我想不出任何开发人员想要使用这些关键字的实际案例。
有人知道这些关键字的任何实际用例吗?
【问题讨论】:
-
不,我不这么认为。
标签: c++ c++11 memory-alignment memory-layout
我刚刚了解了 alignof 和 alignas C++ 关键字,但我想不出任何开发人员想要使用这些关键字的实际案例。
有人知道这些关键字的任何实际用例吗?
【问题讨论】:
标签: c++ c++11 memory-alignment memory-layout
根据我的经验的实际用例:
【讨论】:
alignas 说明符的一个常见用例是,您希望通过队列(例如,事件或任务队列)在不同线程之间传递多个对象,同时避免使用 false sharing。当多个线程实际访问不同的对象时,它们会竞争相同的缓存行,从而导致错误共享。由于性能下降,这通常是不可取的。
例如——假设缓存行大小为64字节——给定以下Event类:
struct Event {
int event_type_;
};
Event 的对齐方式将对应于其数据成员 event_type_ 的对齐方式。假设int 的对齐是4 个字节(即alignof(int) 计算结果为4),则最多16 Event对象可以放入单个缓存行。所以,如果你有这样的队列:
std::queue<Event> eventQueue;
如果一个线程将事件推送到队列的后面,而另一个线程从前面拉事件,我们可能会让两个线程竞争同一个缓存行。但是,通过在Event 上正确使用alignas 说明符:
struct alignas(64) Event {
int event_type_;
};
这样,Event 对象将始终在缓存行边界上对齐,以便缓存行最多包含一个Event 对象。因此,两个或多个线程在访问不同的Event 对象时永远不会竞争同一个缓存行(如果多个线程正在访问同一个Event 对象,它们显然会竞争同一个缓存行)。
【讨论】:
指针上的备用内存:如果指向某个类型的指针由于该类型的对齐而总是以零结尾,那么那些总是为零的位可用于存储其他内容。示例:
class Small { Aligned * ptr; bool b; }; // suppose having many instances
在 64 位架构上至少需要 8+1 个字节,但可以通过仔细合并 ptr 和 bool 将其压缩为 8 个字节。在使用 ptr 之前,您必须对其进行位掩码,但这是一个非常快的指令。 这是内存和cpu之间的权衡。
【讨论】:
memcpying 分配给它们。这个不能被允许修改任何其他对象的值,包括b。但如果这些共享内存,它会。填充字节是对象表示的一部分,因此不能被其他对象任意使用(除非该对象是零大小的)。