Заполнение строки кэша для переменных, кратных размеру строки кэша

Я создаю очень быстрый многопоточный фреймворк для моделирования дискретных событий. Ядро фреймворка использует методы атомарности и программирования без блокировки для достижения очень быстрого выполнения во многих потоках. Это требует от меня выравнивания некоторых переменных по строкам кэша и заполнения оставшегося пространства строк кэша, чтобы у меня не возникало разногласий по строке кэша. Вот как я это делаю:

// 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 () возвращает количество символов, необходимое для заполнения типа ввода до следующей строки кэша. Тем не менее, если я добавлю тип, который имеет размер, кратный числу строк кэша, CLPAD вернет 0. Если вы попытаетесь создать массив нулевого размера, вы получите следующее предупреждение / ошибку:

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

Я знаю, что мог бы изменить CLPAD (), чтобы в этом случае возвращать CACHELINE_SIZE, но тогда я сжигаю пространство строки кэша без причины.

Как я могу сделать объявление ‘padding’ исчезающим, если CLPAD возвращает 0?

4

Решение

Принимая страницу от 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;

Использование:

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
}

Вы можете предоставить функцию для доступа myObj как пожелаешь.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]