Windows для профессионалов


Кэш-линии - часть 2


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

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

Вот пример плохо продуманной структуры данных:

struct CUSTINFO
{

DWORD dwCustomerID;
// в основном "только для чтения1 int nBalanceDue,
// для чтения и записи char szName[100],
// в основном "только для чтения" FILETIME ttLastOrderDate;
// для чтения и записи
};

А это усовершенствованная версия той же структуры.

// определяем размер кэш-линии используемого процессора

#ifdef _X86_
#define CACHE_ALIGN 32
#endif

#ifdef _ALPHA_
#define CACHE_ALIGN 64
#endif

#ifdef _IA64_
#define CACHE_ALIGN ??
#endif

#define CACHE_PAD(Name, BytesSoFar) BYTE Name[CACHE_ALIGN - ((BytesSoFar) % CACHE_ALIGN)]

struct CUSTINFO
{
DWORD dwCustomerID;
// в осноеном "только для чтения"
char szName[100];
// в основном "только для чтения"

// принудительно помещаем следующие элементы в другую кэш-линию
CACHE_PAD(bPad1, sizeof(DWORD) + 100);

int nBalanceDue;
// для чтения и записи
FILETIME ftLastOrderDate;
// для чтения и записи

// принудительно помещаем следующую структуру в другую кэш-линию
CACHE_PAD(bPad2, sizeof(int) + sizeof(FILETIME));

};

Макрос CACHE_ALIGN неплох, но не идеален. Проблема в том, что байтовый размер каждого элемента придется вводить в макрос вручную, а при добавлении, перемещении или удалении элемента структуры — еще и модифицировать вызов макроса CACHE_PAD.В следующих версиях компилятор Microsoft C/C++ будет поддерживать новый синтаксис, упрощающий выравнивание элементов структур. Это будет что-то вроде __declepec(align(32)).

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




Начало  Назад  Вперед