1.1.1 Постановка задачи.
Предлагается написать программу для выполнения суперскалярной обработки элементов массива с использованием технологии MMX, согласно варианту.
5 |
1.1.2 Решение
1.1.2.1 Интерфейс пользователя
Нажимаем кнопку «Заполнение массивов» для инициализации исходных массивов случайно сгенерированными значениями от 0 до 127 и очистки целевого массива.. Нажатие кнопки «ТЕСТ» запускает процесс обработки согласно варианта задания.
1.1.2.2 Текст программы
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1},
intfunc in 'intfunc.pas',
URDTSC in 'URDTSC.pas';
{$R *.res}
begin
Application.Initialize;
Application.Title := 'Задача 4.3';
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask, AdvSpin, Math, jpeg, ExtCtrls;
const
maxmass=16384;
type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
Label2: TLabel;
Run_Test: TButton;
Times_result: TEdit;
Label4: TLabel;
CPU_Speed: TEdit;
Image1: TImage;
Label5: TLabel;
Label6: TLabel;
Label8: TLabel;
GroupBox2: TGroupBox;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
MassInit: TButton;
MasA_visual: TMemo;
MasC_visual: TMemo;
MasB_visual: TMemo;
procedure Run_TestClick(Sender: TObject);
procedure MassInitClick(Sender: TObject);
procedure Initmass;
procedure ProcessNoMMX;
procedure ProcessMMX;
procedure runs_test;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ai,bi,ci:array[1..maxmass] of byte;
implementation
uses intfunc,URDTSC;
{$R *.dfm}
procedure visualmass(var ta:array of byte;var text:TMemo);
var tmp:string;
ct:TStringList;
i:word;
begin
ct:=TStringList.Create();
ct.Clear;
for i:=1 to maxmass do
begin
if(i=maxmass) then tmp:=';'
else tmp:=', ';
ct.Add(inttostr(ta[i])+tmp);
end;
text.Clear;
text.Lines:=ct;
ct.Destroy;
end;
procedure TForm1.Initmass;
var i:word;
begin
for i:=1 to maxmass do
begin
ai[i]:=0;
bi[i]:=random(127);
ci[i]:=random(127);
end;
visualmass(ai,MasA_visual);
visualmass(bi,MasB_visual);
visualmass(ci,MasC_visual);
end;
procedure TForm1.ProcessNoMMX;
var i:word;
begin
for i:=1 to maxmass do
begin
if(bi[i]<ci[i]) then ai[i]:= bi[i]
else ai[i]:=0;
end;
end;
procedure TForm1.ProcessMMX;
var
m:integer;
begin
m:=(maxmass div 8);
asm
mov ecx,m ;//Количество циклов maxmass/8
xor esi,esi ;//Чистим индекс
@l:
movq mm0, qword ptr ci+[esi];
movq mm1, qword ptr bi+[esi];//кешируем элемент
pcmpgtb mm0, mm1 ;//побайтно сравниваем
pand mm0, mm1 ;//выбераем больший байт или ноль
movq qword ptr ai+[esi], mm0;//сохраняем выбранное
add esi,8 ;//приращение счетчика
loop @l ;//цикл
emms ;//для делфи
end;
end;
procedure TForm1.runs_test;
begin
if(RadioButton1.Checked) then ProcessMMX;
if(RadioButton2.Checked) then ProcessNoMMX;
end;
procedure TForm1.Run_TestClick(Sender: TObject);
var Time_Lo, Time_Hi: comp;
Freq : comp;
begin
Freq:=GetFrequence;
CPU_Speed.Text:=FloatToStr(RoundTo(Freq/10E8,-2))+' ГГц';
Time_Lo:=RDTSC;
runs_test;
Time_Hi:=RDTSC;
Times_result.Text:= FloatToStr(RoundTo((Time_Hi-Time_lo)/Freq,-9))+' c';
visualmass(ai,MasA_visual);
end;
procedure TForm1.MassInitClick(Sender: TObject);
begin
initmass;
end;
end.
unit URDTSC;
interface
uses
Windows;
function RDTSC:comp;
function GetFrequence : longword;
implementation
function RDTSC:comp;
var
TimeStamp:record
case byte of
1: (Whole:comp);
2: (Lo,Hi: LongInt);
end;
begin
asm
db $0F, $31
mov [TimeStamp.lo],eax
mov [TimeStamp.Hi],edx
end;
result:= TimeStamp.Whole;
end;
function GetFrequence : longword;
var
Time_Lo, Time_Hi: comp;
begin
Sleep(1);
Time_Lo:= RDTSC;
Sleep(1000);
Time_Hi:= RDTSC;
result:= Round((Time_Hi-Time_lo));
end;
end.
1.1.2.3 Результаты отладки:
После заполнения массивов:
После завершения обработки (с использованием ММХ):
После завершения обработки (без использования ММХ):
Как видим, технология ММХ дает существенный прирост производительности. Обработка одновременно 8 байт и др. оптимизации дают представленный выше результат.
0 коммент.:
Отправить комментарий