Вопрос № 180940: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Выполнить тест производительности процессора с помощью SSE комманд. Благодарю за помощь!...
Вопрос № 180985: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Вычислить произведение элементов матрицы D, больших 2. Dab=ln/xa3(3 степень)+SINyb/ Xa={0.75;-3.1;1} Yb={5.1;0;3.7} Найти наибольший элемент матрицы <...
Вопрос № 180940:
Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Выполнить тест производительности процессора с помощью SSE комманд. Благодарю за помощь!
Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, Alexkharkov! Предлагаю Вашему вниманию следующую программу, которая считает корни квадратные из элементов одномерного массива (матрицу не стал строить, т.к., на мой взгляд, это не принципиально) Ищются корни сначала при помощи SSE, затем просто сопроцессором Для пущей быстроты использованы ассемблерные вставки Подобный расчет делается два раза - для разного количества элементов массива
Описание команды CPUID, которая дает возможности процессора лучше смотреть в оригинале Удачи!
Код:
#include "stdafx.h&
quot;
using namespace std;
//две длины вектора #define MAX1 10000 #define MAX2 10000000
float *pData; //указатель на вектор int iCount; //количество элементов
void fun1() //подпрограмма №1 для расчета с SSE { _asm { mov ebx, pData //адрес масива xor edi, edi //индекс группы элементов mov ecx, iCount //количество элементов shr ecx, 2 //групп в 4 раза меньше (по 4 сразу) sse_loop: movups xmm0, xmmword ptr [ebx+edi] //загружаем
4 числа сразу sqrtps xmm0, xmm0 //квадратные корни (4 шт) movups xmmword ptr [ebx+edi], xmm0 //пишем на то же место add edi, 16 //4*4, сдвигаем индекс loop sse_loop } }
void fun2() //подпрограмма №2 для расчета с сопроцессором { _asm { mov ebx, pData //адрес масива xor edi, edi //индекс mov ecx, iCount //количество fl_loop: fld [ebx+4*edi] //st = очередному элементу fsqrt //кор
ень квадратный fstp [ebx+4*edi] //сохраняем на тоже место inc edi //на следующий loop fl_loop } }
//функция расчитывает длительность работы подпрограммы pfunc() double _benchmark(void (*pfunc)()) { LARGE_INTEGER freq,start,stop; //переменные для расчета длительности int tp; //текущий приоритете
//возвращаем длительность в секундах return (double)(stop.QuadPart - start.QuadPart)/(double)(freq.QuadPart); }
bool isSSE() //проверка на поддержку процесором SSE { bool bRet; //код возврата _asm { mov eax, 1 cpuid //запрашиваем! test edx, 0x2000000 //бит SSE setnz bRet //bRet
= 1, если указанный бит был установлен } return bRet; }
bool isSSE_OS() //проверка на подержку SSE самой ОС { __try { _asm andps xmm0, xmm0; //пробуем выполнить команду SSE } _except (EXCEPTION_EXECUTE_HANDLER) { if (GetExceptionCode() == STATUS_ILLEGAL_INSTRUCTION) { return false; //если попали сюда, значит не поддерживается } } return true; }
void Calc() //расчет корней квад
ратных { //запрашиваем память под массив размера iCount //память, по идее, выделяется на границе параграфа (что нам и надо)
float *pf = (float*)malloc(iCount * sizeof(float));
//заполняем случайными вещественными числами (знаменатель +1 - чтобы не разделить на 0) for (int i=0; i<iCount; i++) pf[i] = (float)rand() / (rand()+1);
pData = pf; //сохраним указатель в глобальной переменной //считаем первой функцией cout<<"Время расчета с SSE = "<<_benchmark(fun1)<<"\t"<<iCount<<" элементов"<<endl; //второй cout<<"Время
расчета без SSE = "<<_benchmark(fun2)<<"\t"<<iCount<<" элементов"<<endl<<endl; free(pf); //освобождаем память }
if (isSSE() && isSSE_OS()) //проверим на возможность использовать SSE { srand((unsigned)time( NULL )); //инициируем генератор псевдослучайных чисел
iCount = MA
X1; //запишем в глобальную переменную первое количество Calc(); //посчитаем iCount = MAX2; //второе количество Calc(); //посчитаем } else cout<<"SSE не подерживается !!!"<<endl;
Найти: - произведение элементов матрицы D, больших 2. - наибольший
элемент матрицы */
#include <stdio.h> #include <math.h> int main(void) { enum {m=3, n=3}; double X[m] = {0.75, -3.1, 1.0}; double Y[n] = {5.1, 0, 3.7}; double D[m][n]; int a, b; double max; /* наибольший элемент матрицы D */ double p; /* произведение элементов матрицы D, больших 2 */ int has_element; /* флаг, содержит элемент, больший двух */
/* Заполнение матрицы D */<
br> for (a=0; a<m; a++) for (b=0; b<n; b++) D[a][b] = log(fabs(pow(X[a],3)+sin(Y[b])));
/* Печать матрицы D */ printf("Матрица D\n"); for (a=0; a<m; a++) { for (b=0; b<n; b++) printf("%8.4f", D[a][b]); printf("\n"); }
/* Произведение элементов матрицы, больших 2 */ for (a=0, has_element=0, p=1.0; a<m; a++) for (b=0; b<n; b++)
if (D[a][b]>2) { p*=D[a][b]; if (has_element == 0) has_element = 1; }
(has_element==1)? printf("Произведение элементов матрицы D, больших 2, p=%7.4f\n", p): printf("Нет элементов матрицы D, больших 2\n");
/* Наибольший элемент матрицы */ for (a=0, max=D[0][0]; a<m; a++) for (b=0; b<n;
b++) if (D[a][b]>max) max = D[a][b];
printf("Наибольший элемент матрицы D, max=%7.4f\n", max); return 0; }
Вывод
Код:
Матрица D -0.6853 -0.8630
-2.2260 3.4248 3.3942 3.4118 -2.6012 0.0000 -0.7547 Произведение элементов матрицы D, больших 2, p=39.6609 Наибольший элемент матрицы D, max= 3.4248
Если требуются пояснения, задавайте вопросы в мини-форуме.
Ответ отправил: Борисыч (Профессор)
Ответ отправлен: 28.11.2010, 12:37
Номер ответа: 264377
Вам помог ответ? Пожалуйста, поблагодарите эксперта за это! Как сказать этому эксперту "спасибо"?
Отправить SMS#thank 264377
на номер 1151 (Россия) |
Еще номера »
Оценить выпуск »
Нам очень важно Ваше мнение об этом выпуске рассылки!
* Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи.
(полный список тарифов)
** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
*** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.