Я создаю очень быстрый многопоточный фреймворк для моделирования дискретных событий. Ядро фреймворка использует методы атомарности и программирования без блокировки для достижения очень быстрого выполнения во многих потоках. Это требует от меня выравнивания некоторых переменных по строкам кэша и заполнения оставшегося пространства строк кэша, чтобы у меня не возникало разногласий по строке кэша. Вот как я это делаю:
// 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?
Принимая страницу от 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
как пожелаешь.
Других решений пока нет …