【问题标题】:Practical use cases for alignof and alignas C++ keywordsalignof 和 alignas C++ 关键字的实际用例
【发布时间】:2020-10-10 19:42:41
【问题描述】:

我刚刚了解了 alignofalignas C++ 关键字,但我想不出任何开发人员想要使用这些关键字的实际案例。

有人知道这些关键字的任何实际用例吗?

【问题讨论】:

标签: c++ c++11 memory-alignment memory-layout


【解决方案1】:

根据我的经验的实际用例:

  • 为嵌入式系统中的网络数据包编写专门的分配器
  • 解决嵌入式系统专用 CPU 中的错误
  • 关于缓存使用的性能优化
  • 将 C++ 对象的一部分提供到需要具体对齐的 C 库中

【讨论】:

    【解决方案2】:

    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 对象,它们显然会竞争同一个缓存行)。

    【讨论】:

      【解决方案3】:

      指针上的备用内存:如果指向某个类型的指针由于该类型的对齐而总是以零结尾,那么那些总是为零的位可用于存储其他内容。示例:

      class Small { Aligned * ptr; bool b; }; // suppose having many instances
      

      在 64 位架构上至少需要 8+1 个字节,但可以通过仔细合并 ptr 和 bool 将其压缩为 8 个字节。在使用 ptr 之前,您必须对其进行位掩码,但这是一个非常快的指令。 这是内存和cpu之间的权衡。

      【讨论】:

      • 实际上不允许编译器执行此操作。指针是微不足道的类型,所以我可以通过memcpying 分配给它们。这个不能被允许修改任何其他对象的值,包括b。但如果这些共享内存,它会。填充字节是对象表示的一部分,因此不能被其他对象任意使用(除非该对象是零大小的)。
      猜你喜欢
      • 2011-10-26
      • 2013-06-10
      • 2016-05-23
      • 2010-09-15
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      相关资源
      最近更新 更多