Правильный способ обеспечить совместное использование с std :: hardware_constructive_interference_size - PullRequest
0 голосов
/ 03 февраля 2019

Каков правильный и переносимый способ обеспечить истинное совместное использование в структуре, достаточно маленькой, чтобы поместиться в кешлайн?Достаточно ли просто убедиться, что структура достаточно мала?Или же он также должен быть выровнен по границе кэша?

Например, если предположить, что размер строки кэша составляет 64 байта, достаточно ли следующего?

struct A {
  std::uint32_t one;
  std::uint32_t two;
};

Или у меня естьчтобы сделать это?

struct alignas(std::hardware_constructive_interference_size) A {
  std::uint32_t one;
  std::uint32_t two;
};

Примечание. Это всегда будет в стеке, поэтому не требуется перераспределения памяти.


Еще одно продолжение, достаточно ли этого длягарантировать отсутствие ложного обмена?

struct A {
public:
  alignas(hardware_destructive_interference_size) std::uint32_t one;
  alignas(hardware_constructive_interference_size) std::uint32_t two;
};

или нужно ли это делать (в случае, если, скажем, hardware_constructive_interference_size <<code>hardware_destructive_interference_size?)

struct A {
public:
  alignas(hardware_destructive_interference_size) std::uint32_t one;
  alignas(hardware_destructive_interference_size) std::uint32_t two;
};

1 Ответ

0 голосов
/ 03 февраля 2019

Второй вариант в настоящее время является лучшим, что вы можете сделать.

Однако не существует 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, а только предположение времени компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...