Выравнивание по строке кэша и знание размера строки кэша - PullRequest
55 голосов
/ 02 сентября 2011

Чтобы предотвратить ложное совместное использование, я хочу выровнять каждый элемент массива по строке кэша. Итак, сначала мне нужно узнать размер строки кэша, чтобы я назначил каждому элементу это количество байтов. Во-вторых, я хочу, чтобы начало массива было выровнено по строке кэша.

Я использую Linux и 8-ядерную платформу x86. Сначала, как мне найти размер строки кэша. Во-вторых, как мне выровнять строку кэша в C. Я использую компилятор gcc.

Таким образом, структура будет следующей, например, при условии, что размер строки кэша равен 64.

element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191

и т. Д. При условии, конечно, что 0-63 выровнено по строке кэша.

Ответы [ 6 ]

76 голосов
/ 02 сентября 2011

Я использую Linux и 8-ядерную платформу x86. Сначала, как найти размер строки кэша.

$ getconf LEVEL1_DCACHE_LINESIZE
64

Передать значение как определение макроса компилятору.

$ gcc -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` ...

Во время выполнения sysconf(_SC_LEVEL1_DCACHE_LINESIZE) может использоваться для получения размера кэша L1.

32 голосов
/ 02 сентября 2011

Чтобы узнать размеры, вам нужно посмотреть его, используя документацию для процессора, на самом деле, нет никакого программного способа сделать это. С другой стороны, большинство строк кэша имеют стандартный размер, основанный на стандартах intels. В x86 строки кэша занимают 64 байта, однако, чтобы предотвратить ложное совместное использование, вам нужно следовать рекомендациям процессора, на который вы ориентируетесь (у Intel есть некоторые особые примечания по процессорам на основе сетевых пакетов), как правило, для этого нужно выровнять до 64 байтов (По информации Intel, вам также следует избегать пересечения 16-байтовых границ).

Для этого в C или C ++ необходимо использовать стандартную функцию aligned_alloc или один из специфических спецификаторов компилятора, таких как __attribute__((align(64))) или __declspec(align(64)). Чтобы заполнить элементы в структуре, чтобы разделить их на разные строки кэша, вам нужно вставить достаточно большой элемент, чтобы выровнять его по следующим 64-байтовым элементам

9 голосов
/ 02 июня 2012

Другим простым способом является просто cat /pro / cpuinfo:

cat / proc / cpuinfo |grep cache_alignment

9 голосов
/ 02 сентября 2011

Не существует полностью переносимого способа получения размера кэша. Но если вы используете x86 / 64, вы можете вызвать инструкцию cpuid, чтобы получить все, что вам нужно знать о кеше, включая размер, размер строки кэша, количество уровней и т. Д. *

http://softpixel.com/~cwright/programming/simd/cpuid.php

(прокрутите немного вниз, страница о SIMD, но в ней есть раздел, получающий строку кэширования.)

Что касается выравнивания ваших структур данных, также не существует полностью переносимого способа сделать это. GCC и VS10 по-разному определяют выравнивание структуры. Один из способов «взломать» это заполнить вашу структуру неиспользованными переменными, пока она не будет соответствовать желаемому выравниванию.

Чтобы выровнять ваши mallocs (), все основные компиляторы также выровняли функции malloc для этой цели.

8 голосов
/ 02 сентября 2011

posix_memalign или valloc можно использовать для выравнивания выделенной памяти в строке кэша.

2 голосов
/ 23 января 2015

Если кому-то интересно узнать, как это легко сделать в C ++, я создал библиотеку с классом CacheAligned<T>, который обрабатывает определение размера строки кэша, а также выравнивание для вашего объекта T, на которое ссылается вызов .Ref() на вашем CacheAligned<T> объекте. Вы также можете использовать Aligned<typename T, size_t Alignment>, если заранее знаете размер строки кэша или просто хотите придерживаться очень распространенного значения 64 (байтов).

https://github.com/NickStrupat/Aligned

...