C++ 变量的缓存线填充是缓存线大小的倍数

C++ 变量的缓存线填充是缓存线大小的倍数,c++,multithreading,caching,simulation,lockless,C++,Multithreading,Caching,Simulation,Lockless,我正在创建一个非常快速的多线程离散事件模拟框架。该框架的核心使用原子和无锁编程技术来实现跨多个线程的快速执行。这需要我将一些变量与缓存线对齐,并填充剩余的缓存线空间,以便不存在缓存线争用。我是这样做的: // compute cache line padding size constexpr u64 CLPAD(u64 _objSize) { return ((_objSize / CACHELINE_SIZE) * CACHELINE_SIZE) + (((_objSize %

我正在创建一个非常快速的多线程离散事件模拟框架。该框架的核心使用原子和无锁编程技术来实现跨多个线程的快速执行。这需要我将一些变量与缓存线对齐,并填充剩余的缓存线空间,以便不存在缓存线争用。我是这样做的:

// compute cache line padding size
constexpr u64 CLPAD(u64 _objSize) {
  return ((_objSize / CACHELINE_SIZE) * CACHELINE_SIZE) +
      (((_objSize % CACHELINE_SIZE) > 0) * CACHELINE_SIZE) -
      _objSize;
}

alignas(CACHELINE_SIZE) MyObject myObj;
char padding[CLPAD(sizeof(myObj))];
这对我来说非常有用,但今天我在使用这种方法来创建新的对象类型时遇到了一个问题。函数的作用是:返回将输入类型填充到下一个缓存行所需的字符数。但是,如果我输入的类型大小正好是缓存线数的倍数,CLPAD将返回0。如果尝试创建零大小的数组,则会出现以下警告/错误:

ISO C++ forbids zero-size array 'padding'
我知道在这种情况下我可以修改CLPAD()以返回CACHELINE_SIZE,但是我会无缘无故地烧掉相当于缓存线大小的空间


如果CLPAD返回0,如何使“padding”声明消失?

std::aligned_storage
中选取一页,我得出以下结论:

template<class T, bool = false>
struct padded
{
    using type = struct
    {
        alignas(CACHELINE_SIZE)T myObj;
        char padding[CLPAD(sizeof(T))];
    };
};

template<class T>
struct padded<T, true>
{
    using type = struct
    {
        alignas(CACHELINE_SIZE)T myObj;
    };
};

template<class T>
using padded_t = typename padded<T, (sizeof(T) % CACHELINE_SIZE == 0)>::type;
模板
结构填充
{
使用type=struct
{
alignas(缓存线大小)T myObj;
字符填充[CLPAD(sizeof(T))];
};
};
模板
结构填充
{
使用type=struct
{
alignas(缓存线大小)T myObj;
};
};
模板
使用padded_t=typename padded::type;
用法:

struct alignas(32) my_type_1 { char c[32]; }; // char c[32] to silence MSVC warning
struct my_type_2 { char c[CACHELINE_SIZE * 2]; }; // ditto

int main()
{
    padded_t<my_type_1> pt0;
    padded_t<my_type_2> pt1;

    sizeof(pt0);    // 128
    alignof(pt0);   // 128

    sizeof(pt1);    // 256
    alignof(pt1);   // 128
}
struct alignas(32)my_type_1{char c[32];};//字符c[32]使MSVC警告静音
结构my_type_2{char c[CACHELINE_SIZE*2];};//同上
int main()
{
填充pt0;
填充pt1;
sizeof(pt0);//128
对齐(pt0);//128
sizeof(pt1);//256
对齐(pt1);//128
}

您可以按自己的意愿提供一个函数来访问myObj。

有什么理由使用嵌套结构吗?您可以只使用
填充的
而不使用嵌套的
类型
(除非这是某种元编程技巧)@AndreyTurkin实际上,您可以不使用嵌套类型。但是,
padded
的类型包含模板参数,而类型别名提供了一个没有模板参数的匿名结构。那么这样做有什么好处呢?类型的数量变少了?符号表变小了?对象大小变小了?是不是“alignof(T)%CACHELINE\u size”应该是“sizeof(T)%CACHELINE\u size”?@nic是的!因为你的实际问题就是这样描述的。很高兴你注意到我的疏忽。这就是为什么我将大小设置为缓存线的倍数。