ДС19в10-Кеширование-памятей (1238920), страница 2
Текст из файла (страница 2)
Для заполнениякеша вызватьtest().2. Вызвать test()снова и измеритьagain and скоростьчтения(МБ/с)}mountain/mountain.c23Core i7 Haswell 2.1 ГГцРазмеры кеш-памятей:• 64 Б блок• 32 КБ ур.1 данные• 256 КБ ур.2 общий• 8 МБ ур.3 общий«Гора» памятиАгрессивнаяпредвыборкаСкорость чтения (МБ/с)16000ур.11400012000100008000ур.260004000ГребнивременнОйлокальностиур.320000s1s3Склоныпростанственнойлокальностиs5Основнаяs7Шаг (кратно 8 байт)8ms9s11128m32m2m512k128k32kРазмер рабочего набора (байт)24Кеширование памятей¢¢Организация и работа кэшаВлияние кэша на быстродействие памяти§ Диаграмма быстродействия памяти§ Реорганизация циклов улучшает пространственную локальность§ Блокирование улучшает временнУю локальность25Пример перемножения матриц¢Описание:§§§§Переменная sumнаходитсяв регистре/* ijk */Перемножение матриц N x N for (i=0; i<n; i++) {for (j=0; j<n; j++) {Всего O(N3) операцийsum = 0.0;N чтений каждого исходногоfor (k=0; k<n; k++)элементаsum += a[i][k] * b[k][j];Каждый результат - сумма Nc[i][j] = sum;значений}§ может накапливаться в}регистре26Анализ вероятности промаха дляматричного умножения¢Допустим:§ Размер линии = 32 байта (достаточно для 4-х 64-битных слов)§ Размер матрицы (N) очень большой1/N приблизительно представляется 0.0§ Кэш недостаточно велик, чтобы содержать несколько строк матрицы§¢Метод анализа:§ Посмотрим на схему доступа во внутреннем циклеjk*iAj=kBiC27Расположение в памяти массивов Си¢Массивы Си хранятся в памяти по строкам§ строки располагаются друг за другом¢Проход по столбцам в одной строке:§ for (i = 0; i < N; i++)sum += a[0][i];§ доступ к последовательно расположенным элементам§ Если размер кэш-блока (B) > 4 байт, действуетпространственная локальность§ вероятность вынужденного промаха = 4 байта / B¢Проход по строкам в одном столбце:§ for (i = 0; i < n; i++)sum += a[i][0];§ Доступ к разнесённым в памяти элементам§ Пространственная локальность отсутствует!§ вероятность вынужденного промаха = 1 (т.е.
100%)28Перемножение матриц (ijk)/* ijk */for (i=0; i<n; i++) {for (j=0; j<n; j++) {sum = 0.0;for (k=0; k<n; k++)sum += a[i][k] * b[k][j];c[i][j] = sum;}}Внутренний цикл:(*,j)(i,*)(i,j)ABCПострокеПостолбцуОдинэлементПромахов в итерации внутреннего цикла:ABC0.251.00.029Перемножение матриц (jik)/* jik */for (j=0; i<n; i++) {for (i=0; j<n; j++) {sum = 0.0;for (k=0; k<n; k++)sum += a[i][k] * b[k][j];c[i][j] = sum;}}Внутренний цикл:(*,j)(i,*)(i,j)ABCПострокеПостолбцуОдинэлементПромахов в итерации внутреннего цикла:ABC0.251.00.030Перемножение матриц (kij)/* kij */for (k=0; k<n; k++) {for (i=0; i<n; i++) {r = a[i][k];for (j=0; j<n; j++)c[i][j] += r * b[k][j];}}Внутренний цикл:(i,k)(k,*)(i,*)ABCОдинэлементПострокеПострокеПромахов в итерации внутреннего цикла:ABC0.00.250.2531Перемножение матриц (ikj)/* ikj */for (i=0; k<n; k++) {for (k=0; i<n; i++) {r = a[i][k];for (j=0; j<n; j++)c[i][j] += r * b[k][j];}}Внутренний цикл:(i,k)(k,*)(i,*)ABCОдинэлементПострокеПострокеПромахов в итерации внутреннего цикла:ABC0.00.250.2532Перемножение матриц (jki)/* jki */for (j=0; j<n; j++) {for (k=0; k<n; k++) {r = b[k][j];for (i=0; i<n; i++)c[i][j] += a[i][k] * r;}}Внутренний цикл:(*,k)(*,j)(k,j)ABCПостолбцуОдинэлементПостолбцуПромахов в итерации внутреннего цикла:ABC1.00.01.033Перемножение матриц (kji)/* kji */for (k=0; j<n; j++) {for (j=0; k<n; k++) {r = b[k][j];for (i=0; i<n; i++)c[i][j] += a[i][k] * r;}}Внутренний цикл:(*,k)(*,j)(k,j)ABCПостолбцуОдинэлементПостолбцуПромахов в итерации внутреннего цикла:ABC1.00.01.034Сводка перемножений матрицfor (i=0; i<n; i++) {for (j=0; j<n; j++) {sum = 0.0;for (k=0; k<n; k++)sum += a[i][k] * b[k][j];c[i][j] = sum;}}for (k=0; k<n; k++) {for (i=0; i<n; i++) {r = a[i][k];for (j=0; j<n; j++)c[i][j] += r * b[k][j];}}for (j=0; j<n; j++) {for (k=0; k<n; k++) {r = b[k][j];for (i=0; i<n; i++)c[i][j] += a[i][k] * r;}}ijk и jik:• 2 чтения, 0 записей• промахов в итерации = 1.25kij и ikj:• 2 чтения, 1 запись• промахов в итерации = 0.5jki и kji:• 2 чтения, 1 запись• промахов в итерации = 2.035Скорость перемножения матриц на Core i7Тактов на итерацию внутреннего.цикла100jki / kjiijk / jikjkikjiijkjikkijikj10kij / ikj150100150200250300350400450500550600650700Размер массива (N)36Кеширование памятей¢¢Организация и работа кэшаВлияние кэша на быстродействие памяти§ Диаграмма быстродействия памяти§ Реорганизация циклов улучшает пространственную локальность§ Блокирование улучшает временнУю локальность37Пример: Перемножение матрицc = (double *) calloc(sizeof(double), n*n);/* Перемножение a и b - матриц размерами n x n */void mmm(double *a, double *b, double *c, int n) {int i, j, k;for (i = 0; i < n; i++)for (j = 0; j < n; j++)for (k = 0; k < n; k++)c[i*n + j] += a[i*n + k] * b[k*n + j];}jc=iab*38Анализ промахов кеша¢Допустим:§ Элементы матриц – double§ Блок кэша = 8 double (64 байта)§ Размер кэша C << n (много меньше n)¢nПервая итерация:§ n/8 + n = 9n/8 промахов=*=*§ После итерации в кэше:(схематично)ширина8 байт39Анализ промахов кеша¢Допустим:§ Элементы матриц – double§ Блок кэша = 8 double (64 байта)§ Размер кэша C << n (много меньше n)¢nВторая итерация:§ Опять:n/8 + n = 9n/8 промахов¢Всего промахов:=*ширина8 байт§ 9n/8 * n2 = (9/8) * n340Блочное перемножение матрицc = (double *) calloc(sizeof(double), n*n);/* Перемножение a и b - матриц размерами n x n */void mmm(double *a, double *b, double *c, int n) {int i, j, k;for (i = 0; i < n; i+=B)for (j = 0; j < n; j+=B)for (k = 0; k < n; k+=B)/* Перемножение мини-матриц размерами B x B */for (i1 = i; i1 < i+B; i++)for (j1 = j; j1 < j+B; j++)for (k1 = k; k1 < k+B; k++)c[i1*n+j1] += a[i1*n + k1]*b[k1*n + j1];}j1c= i1ab*+Размер блока B x Bc41Анализ промахов кеша¢Допустим:§ Блок кэша = 8 doubles§ Размер кэша C << n (много меньше n)§ Четыре блока умещаются в кеш : 4B2 < C¢n/B blocksПервая (блочная) итерация:§ B2/8 промахов в блоке§ 2n/B * B2/8 = nB/4(не считая матрицу c)=Размер блока B x B§ То, что осталось в кэше(схематично)*=*42Анализ промахов кеша¢Допустим:§ Блок кэша = 8 doubles§ Размер кэша C << n (много меньше n)§ Четыре блока умещаются в кеш : 4B2 < C¢Вторая (блочная) итерация:§ Как и на первой итерации§ 2n/B * B2/8 = nB/4¢n/B blocksВсего промахов:§ nB/4 * (n/B)2 = n3/(4B)=*Размер блока B x B43Сводка блокирования¢¢¢¢Без блокирования: (9/8) * n3С блокированием: 1/(4B) * n3Предполагается наибольший размер блока B,ограниченный как 4B2 < C!Причины существенной разницы:§ Матрице присуща временная локальность:3n2 входных данных, 2n3 операций§ Каждый элемент массивов используется O(n) раз!§ При условии, что программа написана правильно§44Сводка кеширования¢Кеш-памяти могут сильно влиять на быстродействие¢В можете использовать это в своих программах§ Фокусируйтесь на внутренних циклах, где возникаетбольшая часть вычислений и обращений в память.§ Старайтесь улучшать пространственную локальность,обращаясь к данным с минимальным шагом 1.§ Старайтесь улучшать временнУю локальность,максимально используя повторно данные,однажды считанные из основной памяти.45.