Практические примеры использования ключевых слов C++ alignof и alignas

Я только что узнал о ключевых словах alignof и alignas C++, но не могу представить ни одного практического случая, когда разработчик хотел бы использовать эти ключевые слова.

Кто-нибудь знает какой-нибудь практический вариант использования этих ключевых слов?


person BegginerNoob    schedule 20.06.2020    source источник
comment
Отвечает ли это на ваш вопрос? Выравнивание памяти: как использовать alignof/alignas?   -  person Adrian Mole    schedule 20.06.2020
comment
Нет, не думаю.   -  person Waqar    schedule 20.06.2020


Ответы (3)


Обычный вариант использования спецификатора alignas — сценарий, в котором вы хотите передать несколько объектов между разными потоками через очередь (например, очередь событий или задач), избегая при этом ложный обмен. Ложное совместное использование произойдет из-за того, что несколько потоков конкурируют за одну и ту же строку кэша, хотя на самом деле они обращаются к разным объектам. Обычно это нежелательно из-за снижения производительности.

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

struct Event {
   int event_type_;
};

Выравнивание Event будет соответствовать выравниванию его элемента данных event_type_. Если предположить, что выравнивание int равно 4 байтам (т. е. alignof(int) оценивается как 4), то до 16 Event объектов может поместиться в один строка кэша. Итак, если у вас есть очередь, например:

std::queue<Event> eventQueue;

Когда один поток помещает события в конец очереди, а другой поток извлекает события из начала, у нас может быть, что оба потока конкурируют за одну и ту же строку кэша. Однако при правильном использовании спецификатора alignas для Event:

struct alignas(64) Event {
   int event_type_;
};

Таким образом, объект Event всегда будет выравниваться по границе строки кэша, так что строка кэша будет содержать максимум объект Event. Поэтому два или более потока никогда не будут конкурировать за одну и ту же строку кэша при доступе к различным объектам Event (если несколько потоков обращаются к одному и тому же объекту Event, они, очевидно, будут конкурировать за одну и ту же строку кэша).

person 眠りネロク    schedule 20.06.2020

Практические примеры использования из моего опыта:

  • написание специализированного распределителя сетевых пакетов во встроенной системе
  • работа над ошибками в специализированном процессоре встроенной системы
  • оптимизация производительности в отношении использования кеша
  • предоставление части объекта C++ в библиотеку C, которая ожидает конкретного выравнивания
person Slimak    schedule 20.06.2020

Запас памяти для указателей: если указатели на тип всегда заканчиваются нулями из-за выравнивания этого типа, то эти всегда нулевые биты можно использовать для хранения чего-то еще. Пример:

class Small { Aligned * ptr; bool b; }; // suppose having many instances

будет занимать не менее 8+1 байт на 64-битной архитектуре, но его можно сжать до 8 байт, тщательно объединив ptr и bool. Прежде чем использовать ptr, вы должны замаскировать его, но это очень быстрая инструкция. Это компромисс между памятью и процессором.

person poke53280    schedule 27.07.2020
comment
Компилятору на самом деле не разрешено делать это. Указатели являются тривиальными типами, поэтому мне разрешено присваивать им значения путем memcpyвхождения в них. Этому нельзя разрешить изменять значение любого другого объекта, включая b. Но если бы они делились памятью, так бы и было. Байты заполнения являются частью представления объекта и поэтому не могут произвольно использоваться каким-либо другим объектом (если только этот объект не имеет нулевого размера). - person Nicol Bolas; 28.07.2020