Второй вариант в настоящее время является лучшим, что вы можете сделать.
Однако не существует 100% портативного способа выравнивания по размерам строк кэша.Константы hardware_constructive_interference_size
и hardware_destructive_interference_size
являются лишь подсказками.Это лучшие догадки компилятора.В конечном итоге вы не знаете размер строки кэша L1 во время компиляции.
Но на практике это обычно не имеет значения, поскольку для большинства архитектур существует типичный размер строки кэша, например, 64 байта для x86.
Еще больше, для небольших структур, как в вашем примере,всегда достаточно естественного выравнивания структуры, чтобы убедиться, что она полностью находится внутри строки кэша.В вашем конкретном примере это означает, что
struct alignas(8) A {
std::uint32_t one;
std::uint32_t two;
};
всегда будет обеспечивать истинное совместное использование, независимо от фактического размера строки кэша L1 во время выполнения, при условии, что размер строки кэша составляет 8 байтов или больше.(Если оно меньше, у вас никогда не будет истинного совместного использования.)
Относительно следующего вопроса: Второй вариант не гарантирует ложного обмена.Первый вариант может привести к ложному совместному использованию, поскольку размер строки кэша может действительно составлять hardware_destructive_interference_size
, и в этом случае вы будете иметь ложное совместное использование (при условии, что hardware_constructive_interference_size
<<code>hardware_destructive_interference_size).
Но впрактика hardware_destructive_interference_size
и hardware_constructive_interference_size
будет иметь одинаковое значение для большинства архитектур.Это несколько сложнее, учитывая, что ни одна из констант не предоставляет вам реальный размер строки кэша L1, а только предположение времени компиляции.