简体   繁体   English

高速缓存行缓存,用于缓存行大小倍数的变量

[英]Cache line padding for variables that are a multiple of cache line size

I am creating a very fast multi-threaded discrete event simulation framework. 我正在创建一个非常快速的多线程离散事件仿真框架。 The core of the framework uses atomics and lockless programming techniques to achieve very fast execution across many threads. 框架的核心使用原子和无锁编程技术来实现跨多个线程的非常快速的执行。 This requires me to align some variables to cache lines and pad the remaining cache line space so that I don't have cache line contention. 这需要我将一些变量与高速缓存行对齐并填充剩余的高速缓存行空间,以便我没有高速缓存行争用。 Here is how I do it: 我是这样做的:

// 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))];

This works great for me, but I stumbled upon an issue today when I was using this methodology for a new object type. 这对我很有用,但是当我将这种方法用于新的对象类型时,我偶然发现了一个问题。 The CLPAD() function returns the amount of chars needed to pad the input type up to the next cache line. CLPAD()函数返回填充输入类型到下一个缓存行所需的字符数量。 However, if I put in a type that is exactly sized a multiple of number of cache lines, the CLPAD returns 0. If you attempt to create a zero sized array, you get this warning/error: 但是,如果我输入一个大小恰好是缓存行数的倍数的类型,则CLPAD返回0.如果您尝试创建零大小的数组,则会收到此警告/错误:

ISO C++ forbids zero-size array 'padding'

I know I could modify CLPAD() to return CACHELINE_SIZE in this case, but then I'm burning a cache line worth of space for no reason. 我知道在这种情况下我可以修改CLPAD()以返回CACHELINE_SIZE,但后来我无缘无故地刻录了一个空间缓存行。

How can I make the declaration of 'padding' disappear if CLPAD returns 0? 如果CLPAD返回0,如何使'padding'的声明消失?

Taking a page from std::aligned_storage<> , I've come up with the following: 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;

Usage: 用法:

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
}

You can provide a function to access myObj however you wish. 您可以根据需要提供访问myObj的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM