Обсудим, как устроен микропроцессор и как заставить его работать максимально эффективно: быстро обрабатывать код и тратить как можно меньше энергии. Знание этих принципов поможет написать хороший код и избежать трудноуловимых ошибок.
2. 2BREST
Александр Степанюк
Разработчик в компании EPAM
С++
Performance
Software Architecture
.NET
Cloud
Safe Code
Aliaksander Stsepaniuk
EPAM Systems, Chief Software Engineer
3. 3BREST
• Что такое CPU
• Структура простого RISC-процессора
• Конвейер CPU
• Параллелизм на уровне инструкций
• Изменение порядка исполнения инструкций
• Ветвления
ПЛАН
6. 6BREST
Что такое центральный процессор?
Центральный процессор (CPU) — это
электронная микросхема, получающая
инструкции компьютерной программы и
выполняющая базовые арифметические,
логические, управляющие операции и
операции ввода-вывода, указанные в
инструкциях.
11. 11BREST
Структура инструкции RISC
1. Загрузка — Instruction Fetching (IF)
2. Декодирование — Instruction Decode (ID)
3. Исполнение инструкции — Execute
IF ID EX
12. 12BREST
Структура инструкции RISC
1. Загрузка — Instruction Fetching (IF)
2. Декодирование — Instruction Decode (ID)
3. Исполнение — Execute (EX)
4. Доступ к памяти — Memory Access
IF ID EX MEM
13. 13BREST
Структура инструкции RISC
1. Загрузка — Instruction Fetching (IF)
2. Декодирование — Instruction Decode (ID)
3. Исполнение — Execute (EX)
4. Доступ к памяти — Memory Access (MEM)
5. Запись результата — Write Back
IF ID EX MEM WB
32. 32BREST
Важно
Процессор работает в режиме конвейера.
В любой такт работы процесcора он исполняет
несколько инструкций, каждая из которых
имеет свою стадию исполнения.
36. 36BREST
Требует, чтобы (1) и (2)
были завершены
Параллелизм на уровне инструкций
Могут исполняться
одновременно
1. e = a + b
2. f = c + d
3. m = e * f
38. 38BREST
Параллелизм на уровне инструкций
Instruction Decode Queue (56)
Reorder Buffer (192)
Unified Reservation Station (60)
ALU ALU Load/
Store
Load/
Store
Store StoreALU ALU
Float
Vector
Branch
Float
Vector
Vector Branch
Ядро Intel Haswell
CISC
42. 42BREST
Требует, чтобы (1) и (2)
были завершены
Изменение порядка выполнения инструкций
1. e = a + b
2. f = c + d
3. m = e * f
(2) Может завершиться
до того, как (1) начнётся
43. 43BREST
Требует, чтобы (1) и (2)
были завершены
Изменение порядка выполнения инструкций
1. e = a + b
2. f = c + d
3. m = e * f
Наличие зависимостей в данных мешает параллельному исполнению инструкций.
(2) Может завершиться
до того, как (1) начнётся
45. 45BREST
Параллелизм на уровне инструкций на практике
// Последовательно:
a++; a++; a++; a++;
// Параллельно:
a++; b++; c++; d++;
Параллельный вариант
выполняется в 5 раз быстрее,
чем последовательный.
47. 47BREST
Важно
Благодаря параллелизму на уровне
инструкций процессор может исполнять
несколько инструкций одновременно.
Зависимости в данных предотвращают
параллельное исполнение инструкций.
57. 57BREST
Важно
Процессор может изменять порядок
выполнения инструкций так, чтобы не
менялся их смысл в одном потоке.
Смысл многопоточного кода может изменяться.
63. 63BREST
Спекулятивное исполнение
Процессор пытается предсказать, какая
ветка кода будет выполнена до того, как это
станет известно доподлинно.
Если предсказание ошибочно, процессор
отменяет результаты выполнения неверно
предсказанной ветки.
68. 68BREST
Влияние ошибочных предсказаний
std::sort(data, data + arraySize);
long sum = 0;
for (unsigned c = 0; c < arraySize; ++c)
{
if (data[c] >= 128) sum += data[c];
}
Если массив предварительно отсортирован,
цикл исполняется в 2-6 раз быстрее.