В общем, народ, мне очень стыдно и все такое. Не заметил такую очевидную вешь, даже когда тов. Dimonka мне почти на нее показал!
Тестировать-то надо при прочих равных, а у меня тело цикла в зависимости от выравнивания начала то умещалось в одну Cache Line, то разбивалось на 2 — вот вам уже два уровня производительности!
Т.е. имеел смысл вот такой код запустить на P3 и Athlon XP и проверить уже для очень короткого цикла (см. ниже).
А что мы пока имеем по части результатов?
На Athlon-64 только три: 1)почти всюду скорость постоянна, 2) если начало цикла отстоит на 4 байта от начала Cache Line, получаем падение производительности где-то на 10% (но — на пустом цикле, так что реально это не ощущается), 3)самое интересное, на что мне пока не ответили в AMD. Если начало 5-байтового цикла начинается со смещения 0C от начала своей 16-байтовой Cache Line (причем (0C,0D,0E) — одна инстр., а (OF, 00) — другая), все, как и полагается, тормозит; но вот если начинается с 0B (когда, казалось бы, весь цикл лежит в одной Cache Line) — тоже тормозит, а когда с 0F (т.е. цикл не только лежит в двух линейках, но еще и первая инструкция разбита по двум линейкам) — работает быстро.
program Test2;
uses
Sysutils,Forms,classes,stdctrls,controls,dialogs,windows;
resourcestring
ProgramStart=
'Program Test;'+#13#10+
'{$AppType Console}'+#13#10+
'uses Sysutils;'+#13#10+
''+#13#10+
' function rdtsc:int64; asm db $0f,$31 end;'+#13#10+
''+#13#10+
'var Time:int64;'+#13#10+
' a,b:array[1..1000] of cardinal;'+#13#10+
' r:array[1..1000]of cardinal;'+#13#10+
' i,addr:integer;'+#13#10+
'begin'+#13#10+
' for i:=1 to 1000 do a[i]:=2;'+#13#10+
' for i:=1 to 1000 do b[i]:=3;'+#13#10+
''+#13#10+
' Time:=RDTSC();'+#13#10+
''+#13#10+
' asm'+#13#10+
' push edx'+#13#10+
' xor ecx,ecx'+#13#10+
' mov edx,100000000'+#13#10;
//NOPs go here
ProgramEnd=
' @Loop:'+#13#10+
' sub edx,1'+#13#10+
' jnz @Loop'+#13#10+
' pop edx'+#13#10+
' mov eax,offset @Loop'+#13#10+
' mov addr,eax'+#13#10+
' end;'+#13#10+
''+#13#10+
' Writeln(format(''%15d%10x'',[(RDTSC()-Time) div 10000,addr]));'+#13#10+
'end.';
var
f:textfile; s,n:string;
st2:tstringlist;
i,j:integer;
Memo:TMemo;
Form:TForm;
begin
Application.Initialize;
Application.CreateForm(TForm,Form);
Form.Position:=poScreenCenter;
Memo:=TMemo.Create(Form);
Memo.Parent:=Form;
Memo.ScrollBars:=ssBoth;
Memo.ReadOnly:=true;
Memo.Align:=alClient;
ShowMessage('Benchmarkig will take about 3 to 5 minutes; '+
'during that time this application will be hidden.'#13#10'Please be patient...');
setlength(s, MAX_PATH);
SetLength(s,GetTempPath(MAX_PATH,@s[1]));
n:=s+'AlignPerfTest.dpr';
for i:=0 to 63 do
begin
AssignFile(f,n);
Rewrite(f);
Write(f,ProgramStart);
for j:=1 to i do
Writeln(f,'nop');
Write(f,ProgramEnd);
CloseFile(f);
WinExec(pchar('dcc32.exe '+n),SW_HIDE);
n:=ChangeFileExt(n,'.exe');
repeat sleep(1000) until fileexists(n);
WinExec(pchar('cmd /c '+n+' >'+ChangeFileExt(n,'.tmp')),SW_HIDE);
n:=ChangeFileExt(n,'.tmp');
st2:=tstringlist.Create;
repeat
repeat sleep(1000) until fileexists(n);
try
st2.LoadFromFile(n);
except
continue;
end;
Memo.Lines.AddStrings(st2);
break;
until false;
st2.Free;
end;
DeleteFile(pchar(n));
DeleteFile(pchar(ChangeFileExt(n,'.exe')));
DeleteFile(pchar(ChangeFileExt(n,'.dpr')));
Form.BringToFront;
Application.Run;
end.
Slicer