Выравнивание данных для обеспечения векторизации / эффективного доступа к кешу - PullRequest
0 голосов
/ 23 ноября 2018

Эта книга гласит следующее:

Для Knights Landing перемещение памяти является оптимальным, когда начальный адрес данных лежит на 64-байтовых границах.

Q1.Есть ли способ динамически запрашивать процессор в коде C ++, чтобы узнать, какой будет оптимальная граница n -байт для процессора, на котором в данный момент выполняется приложение?Таким образом, код будет переносимым.

В книге также говорится:

Как программисты, мы выполняем две задачи: (1) выравниваем наши данные и (2) делаемубедитесь, что компилятор знает, что он выровнен.

(Предположим, что для вопроса ниже мы знаем, что для нашего процессора оптимально, чтобы данные начинались с 64-байтовых границ.)

Что именно это за «данные»?

Предположим, у меня есть класс таким образом:

class Class1_{
    private: 
    int a;//4 bytes
    double b;//8 bytes
    std::vector<int> potentially_longish_vector_int;
    std::vector<double> potentially_longish_vector_double;
    double * potentially_longish_heap_array_double;
    public:
    //--stuff---//
    double * return_heap_array_address() {return potentially_longish_heap_array_double;}
}

Предположим, у меня также есть функции, которые созданы таким образом:

void func1(Class1_& obj_class1);

void func2(double* array);

То есть func1 принимает объект Class1_ по ссылке, а func2 называется func2(obj_class1.return_heap_array_address());

Чтобы соответствовать рекомендации о том, что данные должны быть соответствующим образом выровнены по границе, следует obj_class1 сама ли 64-байтовая граница выровнена для эффективного функционирования func1()?Должен ли potentially_longish_heap_array_double быть выровнен по 64-байтной границе для эффективного функционирования func2()?

Для выравнивания других членов данных класса, которые являются контейнерами STL, поток здесь предлагает, каквыполнить необходимое выравнивание.

Q2.Итак, должен ли сам объект быть соответствующим образом выровнен, как и все элементы данных в нем?

1 Ответ

0 голосов
/ 23 ноября 2018

В общем случае, когда вы выравниваете массивы по границе строки кэша, это максимизирует использование кэша, а также делает массивы соответствующим образом выровненными для любых SIMD-инструкций.Это связано с тем, что единицей передачи между кэш-памятью ОЗУ и ЦП является строка кеша, которая на современных процессорах Intel составляет 64 байта.

Однако повышенное выравнивание также может привести к потере памяти и снижению использования кэша.Обычно только структуры данных на критическом быстром пути вашего приложения могут требовать указания повышенного выравнивания.

Имеет смысл расположить членов ваших классов в порядке {hotness, size}, чтобы наиболее часто используемые члены или элементы, к которым обращаются вместе, находились в одной строке кэша.

Цель оптимизации здесь состоит в том, чтобы уменьшить количество кеш-памяти и пропуски TLB (или уменьшить количество циклов на команду / увеличить количество команд на цикл).Промахов TLB можно уменьшить, используя огромные страницы.

...