C++对齐(何时使用alignas)

16

我最近学习了结构体的大小和对齐方式。我非常熟悉如何使用alignas()修饰符以及其工作原理。我已经看到了一些正确用法的示例(关注语义,而不是实际用例),以及它如何更改类型/变量的大小。

但是,我不知道在我的代码中什么时候使用它是有用的。您能列举一些使用案例吗?开发人员应该在何时手动指定数据的对齐方式?


1
与期望特定对齐方式的设备通信;使用SSE/MMX等技术;利用CPU功能,在数据按特定方式对齐时运行更快——例如,确保给定的“char s [128]”不会分裂成两个CPU缓存行。 - C.M.
1个回答

32

在多线程应用程序中,有很多用例可以使用alignas,尤其是对于延迟敏感的应用程序,例如高频交易应用程序。

Alignas可提供更严格的控制,以使对象在CPU缓存上的布局更快地访问。以下是优化使用的目标,这些都是使用alignas的用例:

  1. 希望避免缓存行无效所造成的不必要的数据失效
  2. 希望通过优化CPU读取来节省CPU周期的浪费

通过使用alignas将内存对齐到缓存行,如何帮助性能
用例1 - 避免缓存行无效 您可以使用alignas来保持由单独线程使用的地址或对象运行在单独的缓存行上,以便一个线程不会意外地使另一个核心的缓存行无效。

实现原理: 考虑这种情况:进程中的一个线程正在核心0上运行,并写入地址xxxx。该地址现在加载到核心0的L1缓存中。 线程2正在访问地址xxxx + n字节。如果这两个地址恰好处于同一缓存行,则线程2的任何写入都将无效地使核心0的缓存行无效。因此,线程0被延迟,直到缓存行被无效并再次加载。这会影响多线程环境下的性能。

用例2 将对象对齐到单独的缓存行,以便对象不会分散在多个缓存行中。这可以节省CPU周期。例如,如果对象大小为118字节,则最好将其对齐到64字节,因为大多数处理器的缓存行大小现在为64字节。

如果您不这样做,您的对象可能会按以下方式布局在64字节的缓存行上。 (例如,假设对象的实际大小为118字节,并且通过自然对齐,大小变为4的倍数,因此为120字节)

Cache line 1<-----Object 1 60Bytes --> <---your Object 4> Bytes ---------->
由于CPU会以缓存行为单位进行读取,您的对象需要在3个CPU周期内读取完毕。如果您想进行优化,请考虑使用alignas(64)。使用此方法,您的对象将始终分散在2个缓存行中。 注意事项:在考虑使用alignas之前,请仔细检查您的对象。原因是错误的方法可能会导致更多的填充,从而浪费更多的L2缓存。可以通过简单的技巧将数据成员按顺序排列,以避免浪费。

希望这可以帮到您,祝您好运!

你赢得了我的“最佳答案”奖项。 - TT_ stands with Russia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接