未知对齐要求时,如何确定含填充的对齐类型总大小?
我有一个由按缓存行对齐的块组成的缓冲区,每个块的有效数据长度是任意值(比如100字节)。已知缓冲区(vector)里的每个元素都按缓存行边界对齐,因此每个块必须添加填充才能让下一个块也满足对齐要求。现在我需要确定单个块包含填充在内的总占用大小,但不知道具体的对齐要求数值(也就是示意图中标记为?的区域的字节大小)。
(示意图说明:每个块包含100字节有效数据 + 填充字节,填充部分的大小就是需要计算的?,目的是让整个块的总大小是缓存行对齐的倍数,确保下一个块起始于新的缓存行)
在线演示代码:
#include <iostream> #include <cstdint> #include <vector> #define LEVEL1_DCACHE_LINESIZE 64 static constexpr size_t chunk_size_bytes = 100; struct alignas(LEVEL1_DCACHE_LINESIZE) AlignedUint8Chunk { uint8_t data[chunk_size_bytes]; }; int main() { std::vector<AlignedUint8Chunk> buf(2); // 在不知道LEVEL1_DCACHE_LINESIZE的情况下跳转到下一个块的30位置 size_t start = 30; // size_t stop = start + ??? }
你可以利用C++的内置特性直接获取包含填充的块总大小,无需手动计算对齐值:
直接使用
sizeof(AlignedUint8Chunk)
结构体的sizeof会自动包含为满足对齐要求而添加的填充字节,返回值就是单个块(有效数据+填充)的总字节数。比如你的例子里,sizeof(AlignedUint8Chunk)会返回128(100字节数据 + 28字节填充,凑成64字节缓存行的2倍)。修改代码中的计算逻辑:
size_t stop = start + sizeof(AlignedUint8Chunk);动态计算对齐后大小(不依赖结构体)
如果没有预先定义带alignas的结构体,可以手动实现对齐大小计算,或结合alignof获取对齐要求:#include <type_traits> // 计算给定数据长度和对齐要求后的总大小 constexpr size_t get_aligned_size(size_t data_size, size_t alignment) { return (data_size + alignment - 1) & ~(alignment - 1); } // 获取结构体的对齐要求 constexpr size_t chunk_alignment = alignof(AlignedUint8Chunk); // 计算包含填充的块总大小 constexpr size_t total_chunk_size = get_aligned_size(chunk_size_bytes, chunk_alignment);获取系统缓存行大小的标准方式
C++17及以后可以用std::hardware_destructive_interference_size(定义在<new>头文件)直接获取系统缓存行大小,等价于手动定义的LEVEL1_DCACHE_LINESIZE:#include <new> constexpr size_t cache_line_size = std::hardware_destructive_interference_size;
总结:最简洁可靠的方式就是用sizeof(AlignedUint8Chunk),它会自动帮你算出包含填充的完整块大小,完全不需要关心具体的对齐数值。
内容的提问来源于stack exchange,提问作者glades

