Лабораторная работа № 5
Исследование влияния кэш-памяти
Цель: исследовать влияние кэш-памяти на скорость обработки массивов различного размера.
Кэш-память является промежуточным хранилищем данных между процессором и оперативной памятью. Она содержит копии наиболее часто используемых блоков данных. Размер кэш-памяти составляет от нескольких килобайт до нескольких мегабайт, а скорость доступа к ней в несколько раз превосходит скорость доступа к оперативной памяти, но уступает скорости обращения к регистрам.
Допустим, некоторая программа производит обработку элементов массива. Если построить график зависимости времени обработки массива от размера массива, то он не должен иметь линейный характер. В месте, соответствующем размеру кэш-памяти, на графике ожидается некоторый скачок. Таким образом мы и поступим. Напишем программу, которая последовательно увеличивает размер массива и производит над ним операции чтения и записи, а время, затраченное на эту обработку замеряет и записывает в файл.
//Подключаем библиотеки
#include <malloc.h>
#include <windows.h>
//Функция замера времени (ассемблерские вставки)
__int64 RTime()
{
_asm _emit 0x0f
_asm _emit 0x31
}
//Файлы вывода
FILE *rout,*wout,*rwout,*wrout;
//Константы К, размер блока и шаг
#define K 512
#define BLOCK_SIZE (745*1024)
#define STEP_FACTOR (1*K)
//Основная процедура
int main()
{
//Проверяем на наличие выходных файлов
if ((rout = fopen("rres.txt", "w"))
== NULL)
{
perror("rres.txt");
return 1;
}
if ((wout = fopen("wres.txt", "w"))
== NULL)
{
perror("qres.txt");
return 1;
}
if ((rwout = fopen("rwres.txt", "w"))
== NULL)
{
perror("rwres.txt");
return 1;
}
if ((wrout = fopen("wrres.txt", "w"))
== NULL)
{
perror("wrres.txt");
return 1;
}
//Устанавливаем приоритет выполнения программы – критический (максимальный)
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
//Результат
double res;
//Массив - вектор
int *matrix;
//Промежуточные переменные
int b,c,i;
float tmp=1;
float cash;
//Переменные результата времени – 64-битные целые числа
__int64 res1,res2;
double stmp=1;
//Выделяем память для вектора
matrix = (int*)malloc(BLOCK_SIZE);
//-----------------Чтение из КЭШа------------
//Начинаем перебирать блоки разного размера
for (b = 1*K; b < BLOCK_SIZE; b += STEP_FACTOR)
{
//Замеряем начальное время
res1=RTime();
//Цикл для увеличения времени выполнения
for (i=0;i<12;i++) {
//Пробегаем по всему блоку и читаем разные куски памяти
for (c = 0; c <= b; c += sizeof(int)*4) {
stmp += *(int*)((char *)matrix + c + 0);
stmp += *(int*)((char *)matrix + c + 4);
stmp += *(int*)((char *)matrix + c + 8);
stmp += *(int*)((char *)matrix + c + 12);
}
}
//Замеряем конечное время
res2=RTime();
//Вычисляем общее время работы
res=res2-res1;
//Считаем кэш в килобайтах
cash=b;
cash=cash/1024;
//Выводим результат в файл
fprintf(rout,"%f %lf\n",cash, res);
}
//----------------------Запись в Кэш --------------------
//Опять же перебираем вектора разного размера
for (b = 1*K; b < BLOCK_SIZE; b += STEP_FACTOR)
{
res1=RTime();
for (i=0;i<12;i++)
{
//Здесь мы просто записываем а не читаем данные из памяти
for (c = 0; c <= b; c += sizeof(int)*4)
{
*(int*)((char *)matrix + c + 0) = tmp;
*(int*)((char *)matrix + c + 4) = tmp;
*(int*)((char *)matrix + c + 8) = tmp;
*(int*)((char *)matrix + c + 12) = tmp;
}
}
res2=RTime();
res=res2-res1;
cash=b;
cash=cash/1024;
fprintf(wout,"%f %lf\n",cash, res);
}
//----------------Сначала чтение, потом запись ----------
for (b = 1*K; b < BLOCK_SIZE; b += STEP_FACTOR)
{
res1=RTime();
for (i=0;i<12;i++)
{
for (c = 0; c <= b; c += sizeof(int)*2)
{
stmp += *(int*)((char *)matrix + c + 0);
stmp += *(int*)((char *)matrix + c + 4);
*(int*)((char *)matrix + c + 0) = tmp;
*(int*)((char *)matrix + c + 4) = tmp;
}
}
res2=RTime();
res=res2-res1;
cash=b;
cash=cash/1024;
fprintf(rwout,"%f %lf\n",cash, res);
}
//-----------------------Сначала запись, потом чтение -----------
for (b = 1*K; b < BLOCK_SIZE; b += STEP_FACTOR)
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.