2014-09-20 2 views
3

Почему в Linux многие структуры используют макрос ____cacheline_aligned_in_smp? Помогает ли это повысить производительность при доступе к структуре. Если да, то как?____cacheline_aligned_in_smp для структуры в linux

+0

Он уменьшает количество строк кеша, которые должны быть синхронизированы логикой слежения за кешем в системе SMP. –

+0

Привет, Пол, Я нашел объяснение: Это макрос, который расширяется до __attribute__ (расширение gcc), которое запрашивает, что так объявленная переменная выделена по адресу, который является целым кратным размера кешины L1. http://vivekbhadra.wordpress.com/article/linux-cacheline-aligned-in-smp-macro-3c84lj4klzp0d-15/ Это правильно? –

+0

Простите, да, я думал, что это было задано - общая идея состоит в том, что, выравнивая выделение на линии кэша, вы минимизируете размер кеша и, следовательно, минимизируете трафик отслеживания кеш-трафика в системе SMP. –

ответ

0

Каждая строка кеша в любом кеше (dcache или icache) имеет архитектуру 64 байта (в x86). Для предотвращения ложной привязки строк кеша требуется арифметическое кэширование. Если строки кэша распределяются между глобальными переменными (больше в ядре). Если одна из глобальных переменных изменена одним из процессоров в кеше, то она отмечает, что строка кэша является грязной. В оставшейся строке CPU cahce она становится устаревшей. Который должен быть сброшен и повторно извлечен из памяти. Это может привести к промахам в кеше. Для этого требуется больше циклов процессора. Это уменьшает производительность системы. Помните, что это для golabl переменных. Большинство структурных данных ядра используют это, чтобы избежать промахов в строке кэша.

0

Linux управляет кэшем ЦП очень похож на TLB. Кэш-память процессора, например кэши TLB, использует тот факт, что программы имеют тенденцию демонстрировать локальность ссылок. Чтобы избежать необходимости получать данные из основной памяти для каждой ссылки, ЦП будет кэшировать очень маленькие объемы данных в кэше ЦП. Часто есть два уровня, называемые кэшами уровня 1 и уровня 2. Кэш-память уровня 2 больше, но медленнее, чем кэш L1, но Linux относится только к кешу уровня 1 или L1.

Кэши процессора организованы в линии. Каждая строка, как правило, довольно мала, обычно 32 байта, и каждая строка выровнена с ее размером границы. Другими словами, строка кэша из 32 байтов будет выровнена по 32-байтовому адресу. В Linux размер строки равен L1_CACHE_BYTES, который определяется каждой архитектурой.

Как адреса преобразуются в строки кэша варьируются от архитектуры, но отображения попадают под тремя заголовками, прямого отображения, ассоциативном и ассоциативный отображение. Прямое сопоставление - это самый простой подход, когда каждый блок памяти отображает только одну возможную линию кеша. При ассоциативном отображении любой блок памяти может отображаться в любой строке кэша. Установить ассоциативное отображение - это гибридный подход, когда любой блок памяти может отображать любую строку, но только внутри подмножества доступных строк.

Независимо от схемы сопоставления, у каждого из них есть одна общая черта, адреса, близкие друг к другу и согласованные с размером кеша, вероятно, будут использовать разные строки. Поэтому Linux использует простые приемы, чтобы попытаться максимизировать использование кэша

  • Часто доступ к структуре поля находятся в начале структуры, чтобы увеличить вероятность того, что только одна строка необходима для адреса обычных полей;
  • Несвязанные элементы в структуре должны попробовать , чтобы быть как минимум размером кеша в байтах, чтобы избежать ложного обмена между CPU;
  • Объекты в общих кэшах, такие как кеш mm_struct, равны , выровненным с кешем процессора L1, чтобы избежать ложного обмена.

Если ЦП ссылается на адрес, отсутствующий в кеше, происходит промахи в кеше, и данные извлекаются из основной памяти. Стоимость пропусков кэш-памяти довольно высока, так как ссылка на кеш обычно может быть выполнена менее чем за 10 нс, где ссылка на основную память обычно будет стоить от 100 нс до 200 нс. Основная задача состоит в том, чтобы иметь как можно больше кешей и как можно меньше промахов в кеше.

Так же, как некоторые архитектуры автоматически не управляют своими TLB, некоторые из них автоматически не управляют своими кэшами CPU. Перехватчики размещаются в местах, где изменяется виртуальное на физическое отображение, например, во время обновления таблицы страниц. Сброс кэша ЦП всегда должен выполняться сначала, так как некоторые процессоры требуют, чтобы виртуальное физическое сопоставление существовало, когда виртуальный адрес очищается от кеша.

Дополнительная информация here

2

____cacheline_aligned инструктирует компилятор для создания экземпляра структуры или переменной в адрес, соответствующий началу в строке кэша L1, для конкретной архитектуры, то есть, так что L1 кэш-строки выровнены , ____cacheline_aligned_in_smp аналогичен, но на самом деле линия L1 выровнена только тогда, когда ядро ​​скомпилировано в конфигурации SMP (то есть с опцией CONFIG_SMP). Они определены в файле include/linux/cache.h

Эти определения полезны для переменных (и структур данных), которые не распределяются динамически через некоторый распределитель, а являются глобальными переменными, связанными с компилятором (аналогичный эффект может выполняются динамическими распределителями памяти, которые могут выделять память при определенном выравнивании).

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

Память переменных, начиная с начала строки кэша, составляет половину работы для этой цели; необходимо также «упаковать с ним» только переменные, которые должны перемещаться вместе. Примером является массивом переменных, где каждый элемент массива должен быть доступен только один центральный процессор (ядро):

struct my_data { 
    long int a; 
    int b; 
} ____cacheline_aligned_in_smp cpu_data[ NR_CPUS ]; 

Такого рода определение потребует от компилятора (в конфигурации SMP ядра), что каждая структура cpu начнется с границы строки кэша. Компилятор, неявно, выделяет дополнительное пространство после каждой структуры процессора, так что структура следующего процессора будет начинаться с границы строки кэша.

Альтернативы раздуть структура данных с размером строки кэша из манекена, неиспользуемые байты:

struct my_data { 
    long int a; 
    int b; 
    char dummy[L1_CACHE_BYTES]; 
} cpu_data[ NR_CPUS ]; 

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

+0

Хорошее объяснение :) –