10

我最近在我的应用程序中遇到了我认为是错误共享的问题,我查阅了Sutter关于如何将我的数据与缓存行对齐的文章。他建议使用以下 C++ 代码:

// C++ (using C++0x alignment syntax)
template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] T data;
   char pad[ CACHE_LINE_SIZE > sizeof(T)
        ? CACHE_LINE_SIZE - sizeof(T)
        : 1 ];
};

我可以看到这是如何工作CACHE_LINE_SIZE > sizeof(T)的——结构cache_line_storage最终占用了一个完整的缓存行内存。但是,当sizeof(T)大于单个缓存行时,我认为我们应该按CACHE_LINE_SIZE - T % CACHE_LINE_SIZE字节填充数据,以便生成的结构的大小是缓存行大小的整数倍。我的理解有什么问题?为什么用 1 个字节填充就足够了?

4

3 回答 3

7

您不能拥有大小为 0 的数组,因此需要 1 才能使其编译。但是,当前的规范草案版本说这种填充是不必要的;编译器必须填充到结构的对齐。

另请注意,如果CACHE_LINE_SIZE小于,则此代码格式错误alignof(T)。要解决此问题,您可能应该使用[[align(CACHE_LINE_SIZE), align(T)]],这将确保永远不会选择较小的对齐方式。

于 2009-11-16T20:53:59.770 回答
3

想象

#define CACHE_LINE_SIZE 32
sizeof(T) == 48

现在,考虑如何[[ align(CACHE_LINE_SIZE) ]]工作。例如:

[[ align(32) ]] Foo foo;

这将迫使sizeof(Foo) == 32n一些人n。即 align() 将在必要时为您填充,以便按照要求Foo foo[10];使每个foo[i]对齐。

所以,在我们的例子中,有了sizeof(T) == 48,这意味着sizeof(cache_line_storage<T>) == 64

因此,对齐方式为您提供了您希望的填充。

However, this is one 'error' in the template. Consider this case:

#define CACHE_LINE_SIZE 32
sizeof(T) == 32

Here we end up with char pad[1];. Which means sizeof(cache_line_storage<T>) == 64. Probably not what you want!

I think the template would need to be modified somewhat:

template <typename T, int padding>
struct pad_or_not
{
   T data;
   char pad[padding];
};

// specialize the 0 case
// As it is late, I am SURE I've got the specialization syntax wrong...
template <typename T, int>
struct pad_or_not<0>
{
   T data;
};

template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] pad_or_not<T, (sizeof(T) > CACHE_LINE_SIZE ? 0 : CACHE_LINE_SIZE - sizeof(T) ) > data;
};

or something like that.

于 2009-11-17T05:39:23.123 回答
0

"You can't have arrays of size 0, so 1 is required to make it compile" - GNU C does allow arrays dimensioned as zero. See also http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html

于 2010-08-25T05:53:06.283 回答