90
Что-то с памятью моей стало Сколько стоит доступ в память, и что с этим делать Антон Орлов Qrator Labs [email protected]

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

Embed Size (px)

Citation preview

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

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

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

[email protected]

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

100 Mpps

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

100 Mpps10 нс / пакет

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

Время, нс

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

L1 L2 L3 RAM

The Myth of RAM

Emil Ernerfeldthttps://github.com/emilk/ram_bench

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

Время, нс

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

L1 L2 L3 RAM

The Myth of RAM

Emil Ernerfeldthttps://github.com/emilk/ram_bench

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

Время, нс

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

L1 L2 L3 RAM

The Myth of RAM

Emil Ernerfeldthttps://github.com/emilk/ram_bench

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

Время, нс

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

L1 L2 L3 RAM

The Myth of RAM

Emil Ernerfeldthttps://github.com/emilk/ram_bench

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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

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

Время, сек

Количество колонок

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

Как понять, что происходит?# 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

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

Как понять, что происходит?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

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

Адресация в 8-канальном 32КБ кэше

063

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

Адресация в 8-канальном 32КБ кэше

04863

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

• Кэш-линия: 64 = 26 байт

Адресация в 8-канальном 32КБ кэше

064863

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

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512

Адресация в 8-канальном 32КБ кэше

064863

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

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512

Адресация в 8-канальном 32КБ кэше

064863

8

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

Адресация в 8-канальном 32КБ кэше

064863

64

8

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26

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

Адресация в 8-канальном 32КБ кэше

06124863

64

8

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26

idx

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

Адресация в 8-канальном 32КБ кэше

06124863

64

8

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26

tag idx

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

Адресация в 8-канальном 32КБ кэше

06124863

64

8

• Кэш-линия: 64 = 26 байт• Всего кэш-линий: 32 КБ / 64 Б = 512• Бакетов: 512 / 8 = 64 = 26

• В каждом бакете:у адресов совпадают 6 бит idx

tag idx

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

#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

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

#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;

}

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

#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;

}

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

#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;

}

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

#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;

}

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

#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

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

Кэш L1 и виртуальная память

06124863

64

8

Виртуальный адрес:

tag idx

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

Кэш L1 и виртуальная память

06124863

64

8

Виртуальный адрес:

tag idx

Страница: 4096 байт (12 бит адреса)

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

Кэш L1 и виртуальная память

06124863

64

8

Виртуальный адрес:

tag idx

061245

Физический адрес:

tag idx

Страница: 4096 байт (12 бит адреса)

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

Кэш L1 и виртуальная память

06124863

64

8

Виртуальный адрес:

tag idx

061245

Физический адрес:

tag idx

Страница: 4096 байт (12 бит адреса)

TLB: кэш для трансляции адресов

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

Проблема мелких страниц

64

8

1. Страница: 4 КБ

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

64

8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ

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

64

8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ

Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше

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

64

8Проблема мелких страниц1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ

Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше

3. TLB маленький!64 × 4 КБ = 512 КБ

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

1. Страница: 4 КБ2. L1 = 8 × 4 КБ = 32 КБ

Что делать?• Повышать ассоциативность (канальность)• Виртуальные адреса в кэше

3. TLB маленький!64 × 4 КБ = 512 КБ

4. Количество страниц256 ГБ / 4 КБ = 64 М!

Проблема мелких страниц

64

8

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Source: http://mechanical-sympathy.blogspot.ru/2013/02/cpu-cache-flushing-fallacy.html

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

Row hammer

Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf

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

Row hammer

Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf

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

Row hammer

Source: https://en.wikipedia.org/wiki/Row_hammerSource: https://www.akkadia.org/drepper/cpumemory.pdf

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

Summary

• Меньше памяти — лучше!• Доступ в память — не O(1)• Меньше промахов в кэши и TLB• Меньше задержки на линках (RDIMM, LRDIMM, ECC)

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

Summary

• Меньше памяти — лучше!• Доступ в память — не O(1)• Меньше промахов в кэши и TLB• Меньше задержки на линках (RDIMM, LRDIMM, ECC)

• Важно помнить про иерархию• Cчетчики• Через уровни можно прыгать

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

Future

1. Parallel → Serial• HMC

2. 3D stacking• 3D TSV RLDIMM• HBM

3. NVRAM

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

Source: http://www.intelsalestraining.com/infographics/memory/3DXPointc.pdf

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

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

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

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

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

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

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

Спасибо за внимание!Вопросы?“What Every Programmer Should Know About Memory”

Ulrich Drepper, 2007

https://www.akkadia.org/drepper/cpumemory.pdf

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

Другие полезные ссылки• 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

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

RDIMM LRDIMM

Source: https://habrahabr.ru/company/hostkey/blog/272063/

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

2.5 ГБ

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

2.5 ГБ

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

2.5 ГБ

L1 TLB

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

2.5 ГБ

L2 TLB

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

256 ГБ

L2 TLB