1

我在以下网页中阅读了有关结构的填充:

http://software.intel.com/sites/default/files/m/2/c/d/3/9/25602-17689_w_spinlock.pdf

正如它所描述的:它建议使用以下语句对同步结构进行填充:

struct syn_str { int s_variable; };
void *p = malloc ( sizeof (struct syn_str) + 127 );
syn_str * align_p = (syn_str *)( (((int) p) + 127) & -128 );

我想到的是,它可以更容易地完成,例如:

 struct syn_str { int s_variable; char padx[124] ; }  in 32-bit OS

或者

 struct syn_str { int s_variable; char padx[120] ; }  in 64-bit OS

因为它喜欢做的就是用 128 个字节填充一个完整的结构,或者我为此错过了什么?

更新:

感谢您提供的所有信息!在发布问题后,我搜索了“对齐结构”,看起来“posix_memalign”似乎是非常正确的函数调用......

4

2 回答 2

4

这有两个原因:

  1. 确保结构不会跨越缓存边界并占用两个缓存行,因此每次访问需要两次提取和两次失效
  2. 确保每个缓存行只有一个结构,并防止错误共享。

与高速缓存行开头的对齐提供了两者。将结构填充到与高速缓存行相同的大小都不能提供。

想象一下,如果你愿意,在一个具有 4 字节 int 和 8 字节 OS 堆对齐以及 128 字节缓存行(非常常见)的系统上的以下结构:

struct bare
{
    int x, y, z, u, v, w;
};

仅添加填充,如下所示:

struct padded
{
    int x, y, z, u, v, w;
    char pad[128 - 6 * sizeof (int)]; // 104
};

不会阻止对象在地址 112 处分配,该地址x, y, z, u分为一页和v, w第二页。所以第一个目标被违反了。另一个对象可以分配在地址 248,与x, y前一个对象的v, w. 所以违反了第二个目标。

然而,

char* block = malloc(sizeof (bare) + 127);
bare* p = reinterpret_cast<bare*>(reinterpret_cast<intptr_t>(block + 127) & ~127);

毫无困难地做出这两个保证,因为每个对象都将从某个缓存行的开头开始。

于 2012-12-26T05:23:31.477 回答
0

不,整数变量的 sizeof 运算符在 64 位系统中仍返回 4。字节大小是实现定义的。

于 2012-12-26T05:00:24.210 回答