Представление чисел. Использование SIMD-расширений x86. Функции замера времени. Куликов Игорь Михайлович kulikov@ssd.sscc.ru Представление чисел 2 Классификация простых типов данных Целочисленные типы данных – – Вещественные типы данных – – 3 Размер данных (char, int, long) Знаковый/без знаковый тип (unsigned, signed) Одинарная точность (float) Двойная точность (double) Целые числа без знака (unsigned char, unsigned int, unsigned long) 123 64 32 16 8 2 1 12310 2 2 2 2 2 2 11110112 6 7 5 4 3 1 0 0 0 1 1 1 1 0 1 1 4 Целые числа со знаком (char, int, long) Структура целого числа со знаком 7 sign 5 0 Целые числа со знаком (char, int, long) 123 64 32 16 8 2 1 12310 2 2 2 2 2 2 11110112 6 5 4 3 1 7 0 0 0 1 1 1 1 0 1 1 6 Знак числа Отрицательные целые числа со знаком Находим двоичное представление модуля числа Находим двоичное дополнение, то есть инвертируем все разряды числа Прибавляем единицу 7 Пример представления отрицательного числа -84 84 84 2 2 2 010101002 6 4 2 010101002 101010112 101010112 12 101011002 7 0 1 0 1 0 1 1 0 0 8 Структура вещественных типов данных A 1 M 2 S 1 M 2 9 E Представление числа 0.15625 в типе float 3 0.15625 1.25 2 fraction 012 M 1.012 exponent E 12710 310 12710 12410 011111002 sign 0 10 Представление числа -118.625 в типе float 11 Структура типа double 12 Допустимые значения Целые числа – – – – Вещественные числа – – 13 char -128 ... 127 unsigned char 0 ... 255 int -2147483648 ... 2147483647 unsigned int 0 ... 4294967295 float: порядок -38…38, значащие знаки 7 double: порядок -308…308, значащие знаки 14 Использование SIMD-расширений x86 14 Векторные операции 15 x= x1 x2 x3 x4 + y= y1 y2 y3 y4 z= z1 = x1 + y1 z2 = x2 + y2 z3 = x3 + y3 z4 = x4 + y4 SIMD (Single Instruction Multiple Data) SIMD-расширения (Single Instruction Multiple Data) были введены в архитектуру x86 с целью повышения скорости обработки потоковых данных. Основная идея заключается в одновременной обработке нескольких элементов данных за одну инструкцию. 16 SIMD (Single Instruction Multiple Data) 17 SIMD (Single Instruction Multiple Data) Арифметика с насыщением Для 8-битного без знакового целого x: обычная арифметика: x=254; x+=3; // результат x=1 арифметика с насыщением: x=254; x+=3; // результат x=255 18 Пример программы скалярного произведения с использованием функций SSE 19 float dot(float *x,float *y,int n) { float sum; int i; __m128 *xx,*yy; __m128 p,s; xx=(__m128 *)x; yy=(__m128 *)y; s=_mm_set_ps1(0); for (i=0;i<n/4;i++) { p=_mm_mul_ps(xx[i], yy[i]); // векторное умножение четырех чисел s=_mm_add_ps(s,p); // векторное сложение четырех чисел } p=_mm_movehl_ps(p,s); // перемещение двух старших значений s в младшие p s=_mm_add_ps(s,p); // векторное сложение p=_mm_shuffle_ps(s,s,1); //перемещение второго значения в s в младшую позицию в p s=_mm_add_ss(s,p); // скалярное сложение _mm_store_ss(&sum,s); // запись младшего значения в память return sum; } SIMD – расширения основных процессоров и область применения SSE для процессоров Intel 3DNow! для процессоров AMD AltiVec для процессоров PowerPC от IBM Область применения: Мультимедиа приложения (видео, графика, звук, …) 20 Функции замера времени 21 Функция clock 22 Библиотечная функция определена в заголовочном файле time.h Прототип clock_t clock(); Возвращает время, прошедшее с момента запуска программы в единицах 1/CLK_TCK секунды Используется в Windows Пример использования функции clock #include <stdio.h> #include <time.h> int main() { double pi; clock_t t; t=clock(); // начало замера времени pi = pi_calculate(); t=clock()-t; // окончание замера времени printf("Time: %lf msec Pi = %lf\n",t*1000.0/CLK_TCK,pi); return 0; } 23 Достоинства и недостатки функции clock Достоинства: Недостатки: 24 высокая платформенная независимость низкая точность, при высокой загрузке процессора – неприемлемая точность, так как измеряется интервал времени, во время которого помимо процесса исследуемой программы исполнялись и другие процессы Функция gettimeofday Библиотечная функция определена в заголовочном файле sys\time.h Прототип int gettimeofday(struct timeval* tv, struct timezone* tz); 25 Время можно вычислить из структуры timeval Используется в UNIX Пример использования функции gettimeofday #include <sys/time.h> struct timeval tv1,tv2,dtv; struct timezone tz; void time_start() { gettimeofday(&tv1, &tz); } double time_stop() { gettimeofday(&tv2, &tz); dtv.tv_sec= tv2.tv_sec - tv1.tv_sec; dtv.tv_usec=tv2.tv_usec - tv1.tv_usec; if(dtv.tv_usec<0) { dtv.tv_sec--; dtv.tv_usec+=1000000; } return dtv.tv_sec*1000.0+dtv.tv_usec/1000.0; } 26 Пример использования функции gettimeofday #include <stdio.h> int main() { double pi; time_start(); // начало замера времени pi = pi_calculate(); // окончание замера времени printf("Time: %lf msec Pi = %lf\n",time_stop(),pi); return 0; } 27 Достоинства и недостатки функции gettimeofday Достоинства: Недостатки: 28 высокая платформенная независимость низкая точность, при высокой загрузке процессора – неприемлемая точность, так как измеряется интервал времени, во время которого помимо процесса исследуемой программы исполнялись и другие процессы Функция times 29 Библиотечная функция определена в заголовочном файле sys/times.h Прототип clock_t times(struct tms *buf); Возвращает время, прошедшее с момента запуска программы в единицах 1/CLK_TCK секунды Используется в UNIX Пример использования функции times #include <sys/times.h> #include <time.h> struct tms tmsBegin,tmsEnd; void time_start() { times(&tmsBegin); } double time_stop() { times(&tmsEnd); return ((tmsEnd.tms_utime-tmsBegin.tms_utime)+ (tmsEnd.tms_stimetmsBegin.tms_stime))*1000.0/CLK_TCK; } 30 Пример использования функции times #include <stdio.h> int main() { double pi; time_start(); // начало замера времени pi = pi_calculate(); // окончание замера времени printf("Time: %lf msec Pi = %lf\n",time_stop(),pi); return 0; } 31 Достоинства и недостатки функции times Достоинства: Недостатки: 32 высокая точность (относительная независимость от других процессов системы) для малых интервалов она зависит от интервала времени прерываний по таймеру Функции QueryPerformanceFrequency и QueryPerformanceCounter 33 Платформенно-зависимый вариант для OS Windows как функция WinAPI Возвращает число тактов с момента запуска процессора Используется в Windows Функции QueryPerformanceFrequency и QueryPerformanceCounter #include <stdio.h> #include <windows.h> int main() { LARGE_INTEGER b_start,b_stop,b_time,freq; double time, pi; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&b_start); pi = pi_calculate(); QueryPerformanceCounter(&b_stop); b_time.QuadPart = b_stop.QuadPart - b_start.QuadPart; time = (double)(b_time.QuadPart)/(double)(freq.QuadPart); printf("Time: %lf sec Pi = %lf\n",time,pi); return 0; } 34 Функции QueryPerformanceFrequency и QueryPerformanceCounter Достоинства: Недостатки: 35 максимально возможная точность зависимость от архитектуры процессора ухудшение точности при высокой загрузке процессора Лабораторные работы 36 Использование SIMD-расширений архитектуры x86 (10 баллов) Использование оптимизирующего компилятора (10 баллов) Исследование вопросов тестирования производительности (20 баллов) Программирование многоядерных архитектур (40 баллов) Выполнение лабораторных работ 37 Первая контрольная неделя – 2 балла: сдана и защищена первая л.р., сдана вторая л.р. – 1 балл : сдана и защищена первая л.р. Вторая контрольная неделя – 2 балла : сданы и защищены первая, вторая и третья л.р. – 1 балл : сдана и защищена первая и вторая л.р. Зачёт – Претендент на автомат: 4 балла за К.Н., сданы и защищены все лабораторные работы – Допуск на зачёт: 51 балл за л.р. (следующая л.р. выполняется только после выполнение текущей) Расписание консультаций 38 Каждый понедельник начиная с 1 марта в 9:00 во 2-м корпусе, аудитория 418