Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Программирование на C / C++


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты данной рассылки

Гаряка Асмик
Статус: Профессор
Рейтинг: 5531
∙ повысить рейтинг »
Boriss
Статус: Академик
Рейтинг: 2552
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2063
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / C/C++

Номер выпуска:1604
Дата выхода:03.12.2010, 09:00
Администратор рассылки:Verena (Профессионал)
Подписчиков / экспертов:334 / 177
Вопросов / ответов:2 / 2

Вопрос № 180940: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Выполнить тест производительности процессора с помощью SSE комманд. Благодарю за помощь!...


Вопрос № 180985: Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос: Вычислить произведение элементов матрицы D, больших 2. Dab=ln/xa3(3 степень)+SINyb/ Xa={0.75;-3.1;1} Yb={5.1;0;3.7} Найти наибольший элемент матрицы <...

Вопрос № 180940:

Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:
Выполнить тест производительности процессора с помощью SSE комманд. Благодарю за помощь!

Отправлен: 25.11.2010, 15:31
Вопрос задал: Alexkharkov (Посетитель)
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич (Старший модератор) :
Здравствуйте, 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; //текущий приоритете


QueryPerformanceFrequency(&freq); //запрвшиваем частоту

if (freq.QuadPart == 0) //проверим на корректность
{
return 0.0f; //ничего не делаем
}

//читаем текущий приоритет
tp = GetThreadPriority(GetCurrentThread());

//если ошибка, то также выходим
if (tp == THREAD_PRIORITY_ERROR_RETURN)
{
return 0.0f;
}

//для уменьшения влияния многозадачности установим "критический"!
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
QueryPerformanceCounter(&start); //начинаем отсчет тиков

(*pfunc)(); //вызываем функцию

QueryPerformanceCounter(&stop); //заканчиваем отсчет
//возвращаем приоритет
SetThreadPriority(GetCurrentThread(),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); //освобождаем память
}

void main()
{
setlocale(LC_ALL,"russian"); //чтобы писалось по-русски

if (isSSE() && isSSE_OS()) //проверим на возможность использовать SSE
{
srand((unsigned)time( NULL )); //инициируем генератор псевдослучайных чисел

iCount = MA X1; //запишем в глобальную переменную первое количество
Calc(); //посчитаем
iCount = MAX2; //второе количество
Calc(); //посчитаем
}
else
cout<<"SSE не подерживается !!!"<<endl;

getchar(); //подождем нажатия на Enter

}

stdafx.h
Код:
#pragma once


#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <math.h>
#include <excpt.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <time.h>
#include <iostream>
#include <locale>


Примерный результат работы:
Код:
Время расчета   с SSE = 4.52571e-005    10000 элементов
Время расчета без SSE = 0.000164546 10000 элементов

Время расчета с SSE = 0.0566709 10000000 элементов
Время расчета без SSE = 0.165188 10000000 элементов

-----
Люби своего ближнего, как самого себя

Ответ отправил: Лысков Игорь Витальевич (Старший модератор)
Ответ отправлен: 29.11.2010, 16:40
Номер ответа: 264411
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru

Оценка ответа: 5

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 264411 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Вопрос № 180985:

    Здравствуйте, уважаемые эксперты! Прошу Вас ответить на следующий вопрос:

    Вычислить произведение элементов матрицы D, больших 2.

    Dab=ln/xa3(3 степень)+SINyb/
    Xa={0.75;-3.1;1}
    Yb={5.1;0;3.7}
    Найти наибольший элемент матрицы

    Зарание благодарю Вас, уважаемые эксперты!

    Отправлен: 28.11.2010, 05:19
    Вопрос задал: Скачков Антон Юрьевич (Посетитель)
    Всего ответов: 1
    Страница вопроса »


    Отвечает Борисыч (Профессор) :
    Здравствуйте, Скачков Антон Юрьевич! G++/Code::Blocks;
    Код:
    /* 180985
    Дано:
    Dab=ln/xa3(3 степень)+SINyb/
    Xa={0.75;-3.1;1}
    Yb={5.1;0;3.7}

    Найти:
    - произведение элементов матрицы 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 (Россия) | Еще номера »
  • Отправить WebMoney:


  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFPRO.RU, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.24 от 30.11.2010

    В избранное