Реализация на основе функции GetTickCount() 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Реализация на основе функции GetTickCount()



 

Итак, для определения производительности жесткого диска, нам необходимо записать на него данные. Мы можем это сделать, выводя данные в файл. Для работы с файлами существует несколько различных наборов функций. Мы воспользуемся функциями CreateFile(), WriteFile() и CloseHandle().

Создание и открытие файла будем осуществлять с помощью функции CreateFile():

 

HANDLE CreateFile(

LPCTSTR lpFileName,

DWORD dwDesiredAccess,

DWORD dwShareMode,

LPSECURITY_ATTRIBUTES lpSecurityAttributes,

DWORD dwCreationDisposition,

DWORD dwFlagsAndAttributes,

HANDLE hTemplateFile);

 

где

lpFileName — указатель на строку содержащую имя и путь к файлу;

dwDesiredAccess — флаги доступа к файлу (для записи, для чтения и др.);

dwShareMode — флаги определяющие общий доступ к файлу;

lpSecurityAttributes — атрибуты безопасности;

dwCreationDisposition — флаги определяющие способ создания файла;

dwFlagsAndAttributes — флаги задающие свойства созданного файла;

hTemplateFile — шаблон файла на основании каких свойств создавать новый файл.

Для записи в файл используем функцию WriteFile():

 

BOOL WriteFile(

HANDLE hFile,

LPCVOID lpBuffer,

DWORD nNumberOfBytesToWrite,

LPDWORD lpNumberOfBytesWritten,

LPOVERLAPPED lpOverlapped);

 

где

 

hFile — манипулятор созданного файла;

lpBuffer — указатель на буфер с данными для записи в файл;

nNumberOfBytesToWrite — количество байт для записи;

lpNumberOfBytesWritten — по этому адресу возвращается количество записанных байт;

lpOverlapped — данные для перекрытого ввода/вывода.

 

Функция возвращает не нулевое значение в случае успешной записи в файл.

После окончания работы с файлом нам необходимо будет его закрыть с помощью функции CloseHandle():

 

BOOL CloseHandle(HANDLE hFile);

 

где

 

hFile – манипулятор закрываемого файла.

 

Функция возвращает ненулевое значение в случае успешного закрытия файла.

Теперь нам осталось решить вопрос измерения времени. Для этого будем использовать функцию GetTickCount(). Прототип функции:

 

DWORD GetTickCount(void);

 

Она возвращает количество миллисекунд прошедших с момента старта компьютера.

С учетом всего вышеизложенного, обработчик OnBstart() будет выглядеть следующим образом.

 

void CHDDTestDlg::OnBstart()

{

// TODO: Add your control notification handler code here

UpdateData(true);

 

double dSpeed; // скорость записи на диск

double dWriteTime; // время записи на диск

char szBuf[255]; // строковый буфер для вывода информации

DWORD dwNumberOfBytesWritten; // количество записанных в файл байт

// динамически создаем буффер для записи

char *pFileBuf = new char [m_nSize];

// заполняем буффер данными (все равно какими). В данном случае символом ‘a’

memset(pFileBuf, ‘a’, m_nSize);

// Создаем файл

HANDLE hFile = CreateFile("C:\\file.dat", FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

// фиксируем время начала записи

DWORD dwTime = GetTickCount();

// записываем данные в файл

WriteFile(hFile, pFileBuf, m_nSize, &dwNumberOfBytesWritten, NULL);

// вычисляем продолжительность записи

dWriteTime = (GetTickCount() – dwTime) / 1000.;

// Закрываем файл

CloseHandle(hFile);

// удаляем буффер

delete[] pFileBuf;

// удаляем файл

DeleteFile("C:\\file.dat");

 

// проверяем не равен ли знаменатель нулю. Это может случиться в том случае

// когда размер данных слишком мал и разрешающей способности функции

// GetTickCount() не достаточно, чтобы зафиксировать длительность процесса

// записи

if (dwTime == 0)

{

sprintf(szBuf, "Малый размер данных");

}

else

{

// рассчитываем скорость записи на диск в МБт/с

dSpeed = m_nSize / (dWriteTime * 1000000.);

sprintf(szBuf, "Скорость записи: %.4g МБт/с", dSpeed);

}

 

m_Proto.AddString(szBuf);

}

 

Реализация на основе таймера высокого разрешения

 

Теперь рассмотрим альтернативную реализацию определения производительности жесткого диска в которой интервалы времени будем измерять при помощи таймера высокого разрешения. Для работы с таким таймером существует две функции QueryPerformanceFrequency() и QueryPerformanceCounter(). Первая позволяет получить частоту работы таймера высокого разрешения (если он существует). Ее прототип:

 

BOOL QueryPerformanceFrequency(LARGE_INTEGER * lpFrequency);

 

где:

lpFrequency — указатель на частоту таймера.

В случае успешного выполнения функция возвращает ненулевое значение.

Функция QueryPerformanceCounter() имеет аналогичный прототип:

 

BOOL QueryPerformanceCounter(LARGE_INTEGER * lpFrequency);

 

и позволяет получить текущее количество тиков таймера высокого разрешения.

Очевидно, что разделив разность тиков между двумя событиями на частоту мы получим время, прошедшее между этими событиями.

Отметим, что частота таймера высокого разрешения зависит от операционной системы. Для Windows 2000/XP она составляет 3579545. Таким образом, таймер высокого разрешения позволяет измерять микросекундные интервалы времени, в то время как функция GetTickCount() — милисекундные.

В целом реализация алгоритма определения производительности жесткого диска с использованием таймера высокого разрешения очень похожа на реализацию с помощью функции GetTickCount(). Код обработчика OnBstart() примет вид:

 

void CHDDTestDlg::OnBstart()

{

// TODO: Add your control notification handler code here

UpdateData(true);

double dSpeed; // скорость записи на диск

char szBuf[255]; // строковый буфер для вывода информации

DWORD dwNumberOfBytesWritten; // количество записанных в файл байт

// динамически создаем буффер для записи

char *pFileBuf = new char [m_nSize];

// заполняем буффер данными (все равно какими). В данном случае символом ‘a’

memset(pFileBuf, ‘a’, m_nSize);

// Создаем файл

HANDLE hFile = CreateFile("C:\\file.dat", FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

LARGE_INTEGER nStart, nStop, nFreq;

double dTime;

// получаем частоту таймера

QueryPerformanceFrequency(&nFreq);

// фиксируем время начала записи

QueryPerformanceCounter(&nStart);

// записываем данные в файл

WriteFile(hFile, pFileBuf, m_nSize, &dwNumberOfBytesWritten, NULL);

// фиксируем время окончания записи

QueryPerformanceCounter(&nStop);

// вычисляем продолжительность записи

dTime = double(nStop.QuadPart - nStart.QuadPart) / nFreq.QuadPart;

// закрываем файл

CloseHandle(hFile);

// удаляем буффер

delete[] pFileBuf;

// удаляем файл

DeleteFile("C:\\file.dat");

if (dTime == 0)

{

sprintf(szBuf, "Малый размер данных");

}

else

{

// рассчитываем скорость записи на диск в МБт/с

dSpeed = m_nSize / (dTime * 1000000);

sprintf(szBuf, "Скорость записи: %.4g МБт/с", dSpeed);

}

m_Proto.AddString(szBuf);

}

 

Ход работы

 

1. Разработать пользовательский интерфейс.

2. Реализовать алгоритм тестирования на основе функции GetTickCount().

3. Реализовать алгоритм тестирования на основе таймера высокого разрешения.

4. Определить производительность произвольного компьютера и сравнить ее с известными данными.

5. Реализовать функции тестирования во внешнем h-файле.

6. Реализовать функции тестирования во внешних h- и срр- файлах.

7. Реализовать функции тестирования во внешнем файле или файлах по желанию. При этом для тестирования должна быть предназначена одна универсальная функция которая выдает результаты определения производительности HDD как с использованием счетчика, так и с использованием таймера высокого разрешения. Сама функция непосредственно должна возвращать код ошибки. В качестве аргумента функции должна выступать структура в поля которой будут заноситься результаты тестирования.

8. Оформить протокол.

 

 


 

Лабораторная работа № 2.
Определение производительности CPU

 

Цель работы: определение производительности процессора на элементарных операциях.

 

Задачи:

— разработать программный код для определения тактовой частоты процессора;

— разработать программный код для определения времени затрачиваемого на выполнение 1000000 арифметических операций сложения, деления, а также на выполнение 1000000 тригонометрических операций;

— используя разработанное ПО провести исследование производительности различных CPU.

 

 

Вычислительные машины управляются по заранее подготовленной программе. За выполнение этой программы отвечает процессор. Любая программа состоит из набора элементарных операций, выполняющие копирование данных, арифметические операции, управление ходом выполнения программы и др.

Элементарным циклом работы процессора является машинный такт. Каждый машинный такт выполняется за строго определённый интервал времени. Такая периодичность обеспечивается тактовым генератором. Количество тактов в единицу времени называется тактовой частотой процессора.

Рассмотрим х86 (32-х разрядную) архитектуру процессора. Для копирования данных используется мнемоническая инструкция ассемблера:

 

mov приемник, источник

 

Источниками и приёмниками могут быть как внутренние регистры, так и ячейки во внешней памяти. Если выполняется операция копирование из одного регистра в другой — то эта операция называется регистр-регистр, если из регистра во внешнюю память, то регистр-память и из памяти в регистр — память-регистр. Необходимо определить количество тактов затрачиваемых на выполнение такой инструкции.

Существует инструкция процессора, которая возвращает кол-во тактов от начала работы процессора — rdtsc в виде 64-х разрядного целого. Результат заносится в регистры EDX (старшие 4-е байта) и EAX (младшие). Ёмкость 32-х разрядного числа позволяет хранить значение до 232, то есть, например процессор с частотой 1 ГГц будет инкрементировать младшее число 4.2 секунды, а только потом инкрементировать старшее число, которое переполнится только за 572 года.

 



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 178; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.15.219.217 (0.023 с.)