Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Создание эффективных приложений для Windows Джеффри Рихтер 2004 (Книга).pdf
Скачиваний:
385
Добавлен:
15.06.2014
Размер:
8.44 Mб
Скачать

Кэш-линии

Если Вы хотите создать высокоэффективное приложение, работающее на многопро цессорных машинах, то просто обязаны уметь пользоваться кэш-линиями процессо ра (CPU cache lines). Когда процессору нужно считать из памяти один байт, он извле кает не только сго, но и столько смежных байтов, сколько требуется для заполнения кэш-линии Такие линии состоят из 32 или 64 байтов (в зависимости от типа процес сора) и всегда выравниваются по границам, кратным 32 или 64 байтам. Кэш-линии предназначены для повышения быстродействия процессора. Обычно приложение работает с набором смежных байтов, и, если эти байты уже находятся в кэше, про цессору не приходится снова обращаться к шине памяти, что обеспечивает существен ную экономию времени.

Однако кэш-линии сильно усложняют обновление памяти в многопроцессорной среде. Вот небольшой пример:

1.Процессор 1 считывает байт, извлекая этот и смежные байты в свою кэш-линию.

2.Процессор 2 считывает тот же байт, а значит, и тот же набор байтов, что и процессор 1; извлеченные байты помещаются в кэш-линию процессора 2.

3.Процессор 1 модифицирует байт памяти, и этот байт записывается в его кэш линию. Но эти изменения еще не записаны в оперативную память.

4.Процессор 2 повторно считывает тот же байт Поскольку он уже помещен в кэшлинию этого процессора, последний не обращается к памяти и, следова тельно, не «видит" новое значение данного байта.

Такой сценарий был бы настоящей катастрофой. Но разработчики чипов прекрас но осведомлены об этой проблеме и учитывают cc при проектировании своих про цессоров В частности, когда один из процессоров модифицирует байты в своей кэш линии, об этом оповещаются другие процессоры, и содержимое их кэш-линий объяв ляется недействительным. Таким образом, в примере, приведенном выше, после из менения байта процессором 1, кэш процессора 2 был бы объявлен недействительным. На этапе 4 процессор 1 должен сбросить содержимое своего кэша в оперативную память, а процессор 2 — повторно обратиться к памяти и вновь заполнить свою кэш линию Как видите, кэшлинии, которые, как правило, увеличивают быстродействие процессора, в многопроцессорных машинах могут стать причиной снижения произ водительности.

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

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

struct CUSTINFO

{

DWORD dwCustomerID;

//в основном "только для чтения1 int nBalanceDue,

//для чтения и записи char szName[100],

//в основном "только для чтения" FILETIME ttLastOrderDate;