Сколько стоит доступ в память, и что с этим делать

Preview:

Citation preview

Что-то с памятью моей сталоСколько стоит доступ в память, и что с этим делать

Антон ОрловQrator Labs

ao@qrator.net

100 Mpps

100 Mpps10 нс / пакет

Время, нс

Размер данных

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

Recommended