Нижегородский Государственный Университет Им. Н.И. Лобачевского Факультет Вычислительной Математики И Кибернетики

advertisement
Нижегородский Государственный Университет
Им. Н.И. Лобачевского
Факультет Вычислительной Математики И Кибернетики
Учебно-исследовательская Лаборатория
"Информационные Технологии"
Техника оптимизации
программ
Куратор: Мееров И.Б.
Разработчики: Зебрин Д.А.
Бадер А.А.
2003
Содержание
1. Введение.
2. Оптимизация использования
оперативной памяти.
3. Оптимизация использования
КЭШа.
ННГУ
2
IT Lab
Если вы собрались
оптимизировать
программу, подумайте...
А ВАМ ЭТО
НАДО?
ННГУ
3
IT Lab
1.1 Виды оптимизации
Современные компьютеры так
мощны, что даже WINDOWS XP
оказывается бессильна их
затормозить!
Крис Касперски
• Оптимизация по времени.
• Оптимизация по требуемой
памяти.
ННГУ
4
IT Lab
1.2 Требования к оптимизирующим
алгоритмам
• Максимальная машинная независимость и
переносимость на другие платформы.
• Трудоёмкость разработки (в т.ч. тестирование) не
должна превышать 10%-15%.
• Алгоритм должен давать выигрыш не менее чем
на 20%-25% в скорости выполнения.
• Оптимизация должна допускать безболезненное
внесение изменений.
ННГУ
5
IT Lab
1.3 Правила оптимизации
1. Прежде, чем оптимизировать код, следует
иметь надёжно работающий не
оптимизированный вариант.
2. Основной прирост оптимизации даёт не
учёт особенностей системы, а
алгоритмическая оптимизация.
3. Прежде чем порываться переписывать
программу на ассемблер, изучите
ассемблерный листинг компилятора на
предмет оценки его совершенства.
ННГУ
6
IT Lab
1.4 Проблемы оптимизации
• Программное непостоянство,
связанное с тем, что в многозадачных
ОС приложение попадает под влияние
чрезвычайно изменчивой окружающей
среды.
• Аппаратное непостоянство, вызванное
внутренней ”многозадачностью”
самого железа.
ННГУ
7
IT Lab
1.5 Возможные решения проблем
• Выбирать замер с наименьшим временем
выполнения, т.к. прогон с минимальным
временем исполнения и представляет
собой измерение, в минимальной степени
испорченное побочными эффектами.
• Аппаратное непостоянство неустранимо
принципиально.
ННГУ
8
IT Lab
2.1.1 Ядро оперативной памяти
Время работы программы
определяется ее самой
медленной частью.
Закон Амдала
• Ядро состоит из множества ячеек, каждая из
которых хранит всего один бит информации.
• На физическом уровне ячейки объединяются
в прямоугольную матрицу, горизонтальные
линейки которой называются строками (Row),
а вертикальные – столбцами (Column) или
страницами (Page).
• Страница является минимальной порцией
обмена с ядром динамической памяти.
ННГУ
9
IT Lab
2.1.2 Интерфейс ядра
• Выводы микросхемы памяти включают в себя
линии адреса, линии данных и специальный
вывод WE – Write Enable (Разрешение записи).
• В случае квадратной матрицы количество
адресных линий сокращается вдвое, но и выбор
конкретной ячейки памяти отнимает вдвое
больше тактов.
• Причем, возникает неоднозначность, что
именно в данный момент находится на
адресной линии: номер строки или номер
столбца?
ННГУ
10
IT Lab
2.1.3 Интерфейс ядра
• Решение этой проблемы потребовало двух
дополнительных выводов, сигнализирующих о наличии
столбца или строки на адресных линиях и окрещенных
RAS (от row address strobe - строб адреса строки) и
CAS (от column address strobe - строб адреса столбца)
соответственно.
• Задержка между подачей номера строки и номера
столбца на техническом жаргоне называется "RAS to CAS
delay" (на сухом официальном языке - tRCD). Задержка
между подачей номера столбца и получением
содержимого ячейки на выходе - "CAS delay" (или tCAC),
а задержка между чтением последней ячейки и подачей
номера новой строки - "RAS precharge" (tRP).
ННГУ
11
IT Lab
2.2 Взаимодействие памяти и
процессора
• Процессор взаимодействует с оперативной
памятью не на прямую, а через специальный
контроллер.
• Запросы процессора обрабатывает чипсет,
который включает в себя :
– Контроллер шины (BIU – Bus Interface Init)
– Контроллер памяти (MCT – Memory Controller)
– Планировщик запросов памяти (MRO – Memory
Request Organizer).
ННГУ
12
IT Lab
2.3 Отображение физических
DRAM-адресов на логические.
Оперативная память это.
- Однородный массив данных , доступ к ячейкам которого
осуществляется посредством 32-разрядных указателей. (с
точки зрения процессора).
- Физическое пространство, которое крайне не однородно и
делится на банки, адреса страниц и номера столбцов. (на
самом деле).
Согласованием интерфейсов оперативной памяти и процессора
занимается чипсет.
Обеспечить эффективную обработку больших массивов
данных без учёта архитектурных особенностей DRAM –
невозможно.
ННГУ
13
IT Lab
2.4 Оптимизация работы с
памятью
• Оперативная память является одним из самых
узких мест, сдерживающих производительность
всей системы.
• Типовые алгоритмы обработки данных задействуют
быстродействие оперативной памяти едва ли на треть,
а зачастую и менее того!
• Грамотно организованный обмен данными
выполняется, как правило, в три – четыре раза
быстрее, причём эффективное взаимодействие с
памятью достижимо на любом языке (в том числе
интерпретируемом!), а не ограничено лишь одним
ассемблером.
ННГУ
14
IT Lab
2.5.1 Разворачивание циклов
Глубокая развёртка цикла сокращает время его
выполнения более чем в 2 раза!
Здесь примеры оптимизированного и не
оптимизированного циклов.
for (a=0; a<666; a++)
// не оптимизированный
x+=p[a];
// цикл
for (a=0; a<666; a+=2)
{
x+=p[a];
// оптимизированный цикл
x+=p[a+1];
// с двукратным разворотом
}
ННГУ
15
IT Lab
2.5.2 Разворачивание циклов (чтение)
100%
90%
время обработки блока
80%
70%
60%
50%
40%
30%
100%100%
66% 93%
62% 98%
55% 50%
54% 40%
53% 48%
51% 38%
1:1
1:2
1:4
1:8
1:16
1:32
1:54
20%
10%
0%
P-III 733/133/100/I815EP
ННГУ
AMD Athlon 1050/100/100/VIA KT133
16
IT Lab
2.5.3 Разворачивание циклов (запись)
120%
время обработки блока
100%
80%
60%
100% 100%
102% 100%
102% 100%
102% 96%
102% 69%
102% 68%
102% 69%
1:1
1:2
1:4
1:8
1:16
1:32
1:64
40%
20%
0%
P-III 733/133/100/I815EP
ННГУ
AMD Athlon 1050/100/100/VIA KT133
17
IT Lab
2.6.1 Устранение зависимостей по
данным
• Если запрашиваемые ячейки оперативной памяти
имеют адресную зависимость по данным (т.е.
попросту говоря, одна ячейка содержит адрес другой),
процессор не может обрабатывать их параллельно и
вынужден простаивать в ожидании поступления
адресов.
• В общем случае время загрузки N ячеек равно:
– Зависимых
t = N*(Tch + Tmem ),
где Tch – латентность чипсета, а Tmem – латентность памяти
– Независимых t =Tch+Tmem+N/C,
где С – пропускная способность подсистемы памяти.
ННГУ
18
IT Lab
2.6.2 Устранение зависимостей по
данным
Тест пропускной способности оперативной памяти
500
450
Пропускная способность (Мб/с)
400
350
300
250
200
150
100
50
184
155
458
268
0
P-III 733/133/100/I815EP
Athlon 1050/100/100/VIA KT133
Чтение зав исимых данных
ННГУ
19
Чтение не зав исимых данных
IT Lab
2.7.1 Параллельная обработка
данных
• Линейное чтение независимых данных ещё не
обеспечивает их параллельной обработки т.к.
чтение двух смежных ячеек в большинстве случаев
инициирует один, а не два запроса к подсистеме
памяти.
• Эффективный алгоритм обработки данных: при
первом проходе цикла память читается с шагом 32
байта (64/128), что заставляет генерировать
запросы чипсету при каждом обращении к памяти.
ННГУ
20
IT Lab
2.7.2 Варианты чтения ячеек
ННГУ
21
IT Lab
Демонстрация эффективности параллельного чтения
700
2.7.3
Пропускная способность (Мбайт/c)
600
500
400
300
200
458
601
636
268
100
0
P-III 733/133/100/I815EP
Athlon 1.050/100/100/VIA KT133
Последов ательное чтение
ННГУ
22
Параллельное чтение
IT Lab
2.8.1 Оптимизация ссылочных
структур данных
Как оптимизировать прохождение по списку, если адрес
следующего элемента заранее неизвестен, а список сильно
фрагментирован?
Первое что приходит на ум: разбить один список на
несколько независимых списков, обработка которых
осуществляется параллельно.
Наиболее оптимальная стратегия разбиения достигается при
разбиении списка на шесть независимых частей. Это чётко
видно из следующей диаграммы.
Можно многократно увеличить производительность
программы, если при добавлении в конец списка не
трассировать весь список, в специальном поле сохранять
указатель на последний элемент в списке.
ННГУ
23
IT Lab
2.8.2
ННГУ
24
IT Lab
2.8.3 Уменьшение размера структур
данных
• При однократном обрабатывании фиксированного
количества элементов структуры данных скорость
обработки обратно пропорциональна шагу
обработки(при условии что размер элемента списка
меньше 32 байт). Следовательно данные в памяти
нужно располагать так плотно, как только это
возможно.
• Производительность системы можно значительно
повысить, если использовать раздельные (separated)
структуры данных.
ННГУ
25
IT Lab
2.9.1 Рассмотрим следующую структуру.
Классическое представление списка – крайне не
оптимально с точки зрения подсистемы памяти
IBM PC
ННГУ
26
IT Lab
2.9.2 Разделение списка и усечение
разрядности указателей
ННГУ
27
IT Lab
Сравнение классического и оптимизированного списков
100%
2.10.4
90%
Время трассировки
80%
70%
60%
50%
40%
30%
20%
30%
100%
100%
27%
10%
0%
P-III 733
Athlon 1.400
Classic
ННГУ
28
Optimized
IT Lab
2.10.1 Группировка операций
чтения с операциями записи
• При обработке больших массивов
данных, многократно превышающих
емкость кэш-памяти всех уровней,
необходимости избегать смешивания
команд чтения памяти с командами
записи в действительности нет.
ННГУ
29
IT Lab
время обработки
140%
130%
120%
110%
100%
90%
80%
70%
60%
50%
40%
30%
20%
10%
0%
2.10.2
60%
69%
без компенсации разв орот а
P-III/733/133/100/I815EP
ННГУ
105%
126%
с компенсацией разв орот а
AMD Athlon 1050/100/100/VIA KT133
30
IT Lab
2.11.1 Оптимизация сортировки
больших массивов данных
• Одному из лучших алгоритмов сортировки
– quick sort требуется О(n*ln n) операций в
среднем и О(n²) в худшем случае.
• Линейный алгоритм – О(n) операций в
худшем случае. На компьютере AMD Athlon
1050 он упорядочивает десять миллионов
чисел всего за 0,3 с., что в сто раз быстрее
алгоритма quick sort!
ННГУ
31
IT Lab
0,3
313,5
0,05
3,6
0,003
0,07
0,001
0,0047
0,00003
0,00035
2.11.2
0,00001
320
300
280
260
240
220
200
180
160
140
120
100
80
60
40
20
0
0,00002
время сортировки (сек)
Сравнение времени сортировки разными алгоритмами
100
1.000
10.000
100.000
1.000.000
10.000.000
qsort
0,00002
0,00035
0,0047
0,07
3,6
313,5
linear sort
0,00001
0,00003
0,001
0,003
0,05
0,3
кол-во сортируемых чисел
ННГУ
32
IT Lab
превосходство линейной сортировки (крат)
270
260
250
240
230
220
210
200
190
180
170
160
150
140
130
120
110
100
90
80
70
60
50
40
30
20
10
0
2.11.3
2,6 2,7
100
P-III 733/133/100/I815EP
ННГУ
15
14
1.000
42 43
10.000
33
37
100.000
AMD Athlon 1050/100/100/VIA KT133
33
143 71
250 250
1.000.000
2.000.000
кол-во сортируемых чисел
IT Lab
3.1 Оптимизация КЭШа
Кэш-подсистема представляет
собой сплошное скопление чудес,
сюрпризов и сказок
Крис Касперски
Кэш (называемый также сверхоперативной памятью)
представляет собой высокоскоростное запоминающее
устройство небольшой емкости для временного хранения
данных, значительно более быстродействующее, чем
основная память, но, в отличии от оперативной памяти,
не адресуемое и непосредственно “невидимое” для
программиста.
ННГУ
34
IT Lab
3.2 Цели и задачи КЭШ-памяти
• Обеспечение быстрого доступа к
интенсивно используемым данным.
• Согласование интерфейсов процессора и
контроллера памяти.
• Упреждающая загрузка данных.
• Отложенная запись данных.
ННГУ
35
IT Lab
3.3 Расположение КЭШа в
иерархии оперативной памяти
ННГУ
36
IT Lab
3.4 Стратегия помещения данных
в КЭШ-память
Чтобы продать что-нибудь ненужное, надо сначала купить
что-нибудь ненужное.
кот Матроскин
• LRU (Least Recently Used) – вытесняет
то, к чему дольше всего не обращались.
• FIFO (First Input First Output) - вытесняет
то, что было загружено раньше всех.
• Randomize-алгоритм – “кидает монетку”.
ННГУ
37
IT Lab
3.5 Упреждающая загрузка
данных
• Загрузка по требованию (on demand).
• Спекулятивная (speculative) –
необходимы алгоритмы угадывания
– неинтеллектуальные алгоритмы
– интеллектуальные алгоритмы.
ННГУ
38
IT Lab
3.6 Организация КЭШа
• Понятие кэш-линейки (cash-line).
• Понятие ассоциативности КЭШа
(прямое отображение).
• Наборно-ассоциативный КЭШ.
• Политика записи
– сквозная запись (WT – Write True write policy)
– обратная политика записи (WB – Write Back write
policy).
ННГУ
39
IT Lab
3.7 Двухуровневая
организация КЭШа
ННГУ
40
IT Lab
3.8.1 КЭШ-подсистема
современных процессоров
• MOB (Memory Order Buffer – буфер
упорядоченной записи в память).
• L1-Cashe.
• Буферы записи.
• Блок интерфейсов с памятью (MIU).
• Блок интерфейсов с шиной (BIU).
• L2-Cashe.
• Двойная независимая шина (DIB – Dual
Independent Bus).
ННГУ
41
IT Lab
3.8.2 Основные характеристики
• Размер кэша первого уровня.
• Степень ассоциативности и размер
банков кэша.
• Политика записи.
• Длина кэш-линий.
ННГУ
42
IT Lab
3.9 Влияние размера обрабатываемых данных
на производительность (для AMD K6)
500
удельное время обработки одной ячейки
450
400
350
300
250
200
150
100
50
0
1
33 65 97 129 161 193 225 257 289 321 353 385 417 449 481 513 545 577 609 641 673 705
R
ННГУ
W
RW
WR
43
размер обрабатываемого блока (Кб)
IT Lab
3.10.1 Влияние размера исполняемого
кода на производительность
При
разработке
программы
стремитесь проектировать ее так, чтобы
все
часто
используемые
циклы
вмещались в кэш первого или по
крайней мере второго уровня.
ННГУ
44
IT Lab
3.10.2 Изменение удельного времени
выполнения команд
35
удельное время выполнения одной команды
30
25
20
15
10
5
0
размер исполняемого болока (Кб)
4
8
16
32
64
128
256
512
1024
2048
Athlon
1,18
1,14
1,2
1,1
1,09
3,79
3,8
30,9
32,65
32,65
P-III
2,6
2,5
2,5
3,3
3,3
3,3
3,3
14
14
14
ННГУ
45
IT Lab
3.11.1 Выравнивание данных
Выравнивание данных необходимо, когда
данные выходят за границу кэш-линейки и
своим “хвостом” попадают в следующую
кэш-линейку – операция чтения занимает
уже 6-12 тактов, а данные называются
расщепленными (англ. Line-splint).
ННГУ
46
IT Lab
3.11.2 Виды выравнивания
• Естественное выравнивание.
• Выравнивание пользователем: #pragma
pack. Пример “плохой” и “хорошей”
программы:
static int a;
static char b;
static int c;
static char d;
ННГУ
static int a;
static int c;
static char b;
static char d
47
IT Lab
3.12 Учет ограниченной
ассоциативности КЭШа
Обработка ячеек памяти с шагом,
равным или кратным размеру КЭШбанка, крайне не производительна и
этого любой ценой следует избегать.
Пример “плохой” программы:
for (a=0; a<googol; a++) {
a1=bar[4096]; a2=bar[4096]; a3=bar[4096];
a4=bar[4096]; a5=bar[4096]; }
ННГУ
48
IT Lab
3.13.1 Предвыборка
• Предвыборка позволяет программисту
заранее загружать в кэш ячейки памяти, к
которым рассчитывает обращаться в
будущем.
• “Ручное” управление КЭШ-контроллером
позволяет выбрать оптимальную
стратегию упреждающей загрузки
данных.
ННГУ
49
IT Lab
3.13.2 Проблема разницы
архитектуры
• Реализация программной предвыборки
различны для разных типов процессоров
(Intel и AMD).
• Приходится реализовывать функции,
использующие предвыборку в 2
вариантах, что зачастую “съедает”
выигрыш в производительности.
ННГУ
50
IT Lab
3.13.3 Аппаратная предвыборка в
микропроцессоре Pentium-4
• P-4 отслеживает регулярные шаблоны
обращения к данным, что позволяет
предугадывать , к каким КЭШ-линейкам в
будущем произойдет обращение.
• Алгоритм: распознавание арифметическую
прогрессию и вычислять ее члены.
• Упреждающая загрузка осуществляется только
в пределах одного 4-килобайтового блока
памяти, при выходе за его пределы
отслеживание шаблонов начинается с начала.
ННГУ
51
IT Lab
3.13.4 Предпочтительная КЭШиерархия
• Для многократно используемых данных
предпочтительно делать предвыборку в
КЭШ-уровни всех иерархий.
• Однократно используемые данные и
данные гарантированно не вытесняемые
из КЭШа первого уровня в КЭШ второго
уровня загружать нецелесообразно.
ННГУ
52
IT Lab
3.13.5 Практическое
использование предвыборки
• Смысл использовать предвыборку появляется
тогда, когда мы можем предсказать адрес
следующей обрабатываемой ячейки.
• Максимальная производительность достигается
в случаях:
- предвыборка данных происходит в кэшиерархию, соответствующую их назначению.
- запрашиваемые данные загружаются в точности
к моменту обращения.
- происходит предвыборка только тех данных,
которые действительно необходимы.
ННГУ
53
IT Lab
3.13.6 Увеличение эффективности
• Предотвращение холостого хода.
• Уменьшение количества инструкций
предвыборки.
ННГУ
54
IT Lab
Заключение
• Разворачивайте циклы, читающие память.
• Отправляйте контроллеру памяти несколько запросов
одновременно.
• Группируйте операции чтения памяти с операциями записи.
• Используйте все страницы памяти к которым обращались,
целиком.
• Комбинируйте вычисления с доступом к памяти.
• Обращайтесь к памяти только тогда, когда это действительно
необходимо.
• Никогда не оптимизируйте программу на отдельно взятой
машине.
• Циклы, которые часто используются, должны умещаться в
КЭШ
• Следите за выравниванием данных при объявлении
переменных
• Используйте предвыборку данных, когда это возможно
ННГУ
55
IT Lab
Литература
• Техника оптимизации программ. Эффективное
использование памяти. Крис Касперски
• Intel Processor Identification and the CPUID
Instruction (www.intel.com)
• Intel Architecture Software Developer’s Manual
(www.intel.com)
• Intel Architecture Optimization Manual
(www.intel.com)
ННГУ
56
IT Lab
Download