Upload
ontico
View
115
Download
1
Embed Size (px)
Citation preview
Что-то с памятью моей сталоСколько стоит доступ в память, и что с этим делать
Антон ОрловQrator Labs
100 Mpps
100 Mpps10 нс / пакет
100 Mpps10 нс / пакет
Image source: http://www.esaitech.com/supermicro-x9drw-7tpf-b-intel-c602-lga-2011-ddr3-1600mhz-proprietary-wio-server-motherboard.html
100 Mpps10 нс / пакет
1 такт: 3.5 см
Image source: http://www.esaitech.com/supermicro-x9drw-7tpf-b-intel-c602-lga-2011-ddr3-1600mhz-proprietary-wio-server-motherboard.html
100 Mpps10 нс / пакет
1 такт: 3.5 см1 нс: 11 см
Image source: http://www.esaitech.com/supermicro-x9drw-7tpf-b-intel-c602-lga-2011-ddr3-1600mhz-proprietary-wio-server-motherboard.html
Время, нс
Размер данных
L1 L2 L3 RAM
The Myth of RAM
Emil Ernerfeldthttps://github.com/emilk/ram_bench
Время, нс
Размер данных
L1 L2 L3 RAM
The Myth of RAM
Emil Ernerfeldthttps://github.com/emilk/ram_bench
Время, нс
Размер данных
L1 L2 L3 RAM
The Myth of RAM
Emil Ernerfeldthttps://github.com/emilk/ram_bench
Время, нс
Размер данных
L1 L2 L3 RAM
The Myth of RAM
Emil Ernerfeldthttps://github.com/emilk/ram_bench
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS/2; i++)
mat[i][j] = (char)j;}for (int j = 0; j < ROWS; j++) {
for (int i = COLUMNS/2; i < COLUMNS; i++)mat[i][j] = (char)j;
}int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
1.96s
Время, сек
Количество колонок
Как понять, что происходит?# likwid-perfctr -E L1Found 13 event(s) with search key L1:
PAGE_WALKER_LOADS_ITLB_L1
MEM_LOAD_UOPS_RETIRED_L1_HIT
MEM_LOAD_UOPS_RETIRED_L1_MISS
MEM_LOAD_UOPS_RETIRED_L1_ALL
L2_TRANS_L1D_WB
L1_POWER_CYCLES
L1D_PEND_MISS_PENDING
L1D_PEND_MISS_PENDING_CYCLES
L1D_PEND_MISS_OCCURRENCES
L1D_REPLACEMENT
CYCLE_ACTIVITY_CYCLES_L1D_MISS
CYCLE_ACTIVITY_STALLS_L1D_MISS
PAGE_WALKER_LOADS_DTLB_L1
https://github.com/RRZE-HPC/likwid
Как понять, что происходит?Events:
• L1D_REPLACEMENT 911,569,595 51,124,840
• L2_TRANS_L1D_WB 957,062,801 54,446,831
Metric:
• L2 data volume [GBytes] 119.5931 6.7568
Адресация в 8-канальном 32КБ кэше
063
Адресация в 8-канальном 32КБ кэше
04863
• Кэш-линия: 64 = 26 байт
Адресация в 8-канальном 32КБ кэше
064863
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512
Адресация в 8-канальном 32КБ кэше
064863
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512
Адресация в 8-канальном 32КБ кэше
064863
8
Адресация в 8-канальном 32КБ кэше
064863
64
8
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26
Адресация в 8-канальном 32КБ кэше
06124863
64
8
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26
idx
Адресация в 8-канальном 32КБ кэше
06124863
64
8
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26
tag idx
Адресация в 8-канальном 32КБ кэше
06124863
64
8
• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26
• В каждом бакете:у адресов совпадают 6 бит idx
tag idx
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS);
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
12.32s
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS + 64*i) + 64*i;
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS + 64*i) + 64*i;
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS + 64*i) + 64*i;
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS + 64*i) + 64*i;
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
#define COLUMNS 10#define ROWS (1<<28) // 256MB
int main () {char* mat[COLUMNS];for (int i = 0; i < COLUMNS; i++)
mat[i] = (char*)malloc(ROWS + 64*i) + 64*i;
for (int j = 0; j < ROWS; j++) {for (int i = 0; i < COLUMNS; i++)
mat[i][j] = (char)j;}
int res = 0;for (int i = 0; i < COLUMNS; i++)
res += mat[i][i];return res;
}
2.12s
Кэш L1 и виртуальная память
06124863
64
8
Виртуальный адрес:
tag idx
Кэш L1 и виртуальная память
06124863
64
8
Виртуальный адрес:
tag idx
Страница: 4096 байт (12 бит адреса)
Кэш L1 и виртуальная память
06124863
64
8
Виртуальный адрес:
tag idx
061245
Физический адрес:
tag idx
Страница: 4096 байт (12 бит адреса)
Кэш L1 и виртуальная память
06124863
64
8
Виртуальный адрес:
tag idx
061245
Физический адрес:
tag idx
Страница: 4096 байт (12 бит адреса)
TLB: кэш для трансляции адресов
Проблема мелких страниц
64
8
1. Страница: 4 КБ
64
8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ
64
8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ
Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше
64
8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ
Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше
3. TLB маленький!64 × 4 КБ = 512 КБ
1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ
Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше
3. TLB маленький!64 × 4 КБ = 512 КБ
4. Количество страниц256 ГБ / 4 КБ = 64 М!
Проблема мелких страниц
64
8
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html
Row hammer
Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf
Row hammer
Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf
Row hammer
Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf
Summary
• Меньше памяти — лучше!• Доступ в память — не O(1)• Меньше промахов в кэши и TLB• Меньше задержки на линках (RDIMM, LRDIMM, ECC)
Summary
• Меньше памяти — лучше!• Доступ в память — не O(1)• Меньше промахов в кэши и TLB• Меньше задержки на линках (RDIMM, LRDIMM, ECC)
• Важно помнить про иерархию• Cчетчики• Через уровни можно прыгать
Future
1. Parallel → Serial• HMC
2. 3D stacking• 3D TSV RLDIMM• HBM
3. NVRAM
Source: http://www.intelsalestraining.com/infographics/memory/3DXPointc.pdf
NVRAM в качестве основной памяти?
1: node = nvm_alloc(sizeof(node_t));2: node->value = val;3: node->next = head;4: head = node;
Source: http://www.hpl.hp.com/techreports/2012/HPL-2012-236.pdf
NVRAM в качестве основной памяти?
1: node = nvm_alloc(sizeof(node_t));2: node->value = val;3: node->next = head;4: head = node;
Intel:● CLWB (Cache Line Write Back)● PCOMMIT (to Persistent storage COMMIT)
Source: http://www.hpl.hp.com/techreports/2012/HPL-2012-236.pdf
NVRAM в качестве основной памяти?
1: node = nvm_alloc(sizeof(node_t));2: node->value = val;3: node->next = head;4: head = node;
Intel:● CLWB (Cache Line Write Back)● PCOMMIT (to Persistent storage COMMIT)
Source: http://www.hpl.hp.com/techreports/2012/HPL-2012-236.pdf
Спасибо за внимание!Вопросы?“What Every Programmer Should Know About Memory”
Ulrich Drepper, 2007
https://www.akkadia.org/drepper/cpumemory.pdf
Другие полезные ссылки• Dick Sites, Datacenter Computers: modern challenges in CPU designВидео: https://www.youtube.com/watch?v=QBu2Ae8-8LMСлайды: http://www.pdl.cmu.edu/SDI/2015/slides/DatacenterComputers.pdf
• What's new in CPUs since the 80s and how does it affect programmers?http://danluu.com/new-cpu-features/
• Row hammer Android exploit https://www.vusec.net/projects/drammer/
• Kumud Bhandari, Dhruva R. Chakrabarti, Hans-J. Boehm, Implications of CPU Caching on Byte-addressable Non-Volatile Memory Programminghttp://www.hpl.hp.com/techreports/2012/HPL-2012-236.pdf
RDIMM LRDIMM
Source: https://habrahabr.ru/company/hostkey/blog/272063/
2.5 ГБ
2.5 ГБ
2.5 ГБ
L1 TLB
2.5 ГБ
L2 TLB
256 ГБ
L2 TLB