18.10.2009, 23:40
общий
это ответ
Здравствуйте, Dimarik59.
Программа в приложении.
Рассматриваем матрицу 4х4, как вектор размерности 16
В результате получаем ту же задачу, что и приведена, только с той разницей, что умножаем сам на себя.
Кроме того, сделал так, чтобы был вывод русскими буковками.
Убрал вывод начального значения res=res1=0
Если что не понятно, спрашивайте в мини-форуме
Приложение:
#include <iostream> //для применения потокового ввода/вывода (cout, wcout)
#include <locale> //для русских сообщений
#include <windows.h> //для GetTickCount
using namespace std; //для применения потокового ввода/вывода (cout, wcout)
int main(int argc, char* argv[])
{
short a_array[4][4]; //матрица 4х4
short cnt = 16; //число элементов
int res = 0, res1 = 0; //результаты расчетов
int Time1, Time2, Delay1;//для хранения времени
double Speedup; //для хранения эффективности (вещественное число)
locale::global(locale("Russian_Russia.866")); //чтобы писалось по-русски
for (int i=0; i<4; i++) //проинициализируем матрицу
for (int j=0; j<4; j++)
a_array[i][j] = i*4+j;
wcout<<endl<<L" Скалярное произведение с ММХ и без..."<<endl<<endl;
// Заметить время...
Time1 = GetTickCount();
// Многократный прогон кода с MMX ...
for (i=0; i<10000000; i++)
{
cnt = 16; //число элементов
__asm
{
push eax //сохраним используемые регистры
push ecx
push esi
xor esi, esi //индекс в массиве
pxor MM7, MM7 //обнулим MM7 - сумма квадратов
loop1:
movq MM0, a_array[esi] //загрузим 4 элемента массива в MM0
movq MM1, MM0 //скопируем в MM1
pmaddwd MM0, MM1 //умножим попарно 4 элемента, результат в MM0,
// плюс сложим 1 с 2, 3 с 4
paddd MM7, MM0 //накапливаем суммы в MM7
add esi, 8 //на следующие 4 слова
sub cnt, 4 //по 4 слова за раз
jnz loop1 //циклим
//теперь надо сложить два 32-битных числа
movq MM0, MM7 //копируем в MM0
psrlq MM7, 32 //сдвигаем MM7 на 32 разряда вправо
paddd MM7, MM0 //складываем
movd res, MM7 //сохраняем
emms //сброс MMX
pop esi //восстановим регистры
pop ecx
pop eax
}
}
Time2 = GetTickCount(); //Еще раз замерим время
wcout<<endl<<L" С использованием ММХ ... "<<endl; //выведем результат
cout<<endl<<"Result = "<<res;
Delay1 = Time2 - Time1; //выведем разность времени
wcout<<endl<<L"Прошедшее время = "<<Delay1<<L" ms"<<endl;
// Заметить время ...
Time1 = GetTickCount();
// Многократный прогон кода без MMX ...
for (i=0; i<10000000; i++)
{
cnt = 16; //число элементов
__asm
{
push eax
push ecx
push esi
xor esi, esi //индекс
xor ecx, ecx //сумма
loop2:
movsx eax, a_array[esi] //Чтение из памяти (расширяем слово на двойное слово)
imul eax, eax //квадрат
add cx, ax //накапливаем (значащая часть только в ax)
add esi, 2 //сдвигаем указатель
sub cnt, 1 //счетчик
jnz loop2 //на повтор
mov res1, ecx //результат
pop esi
pop ecx
pop eax
}
}
Time2 = GetTickCount();
wcout<<endl<<L" Без использования ММХ ... "<<endl;
wcout<<endl<<L"Result1 = "<<res1<<endl<<L"Прошедшее время = "<<Time2-Time1<<L" ms"<<endl;
//расчитаем еффективность, как отношение времен
Speedup = float(Time2 - Time1)/float(Delay1);
wcout<<endl<<L"Эффективность MMX = "<<Speedup<<L" раз"<<endl<<endl;
return 0;
}
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен