как заставить FPC генерить правильный SSE код

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Сообщение Sniper » 29.06.2005 20:40:01

Чёто не могу заюзать с указателями! =(
Код: Выделить всё
program test_fpc;
{$APPTYPE CONSOLE}

uses windows;
type
pTVector = ^TVector;
TVector = record
x, y, z: single;
end;

procedure le_CrossVector(Vector1, Vector2, VectRes: pTVector);  overload;
begin
VectRes^.X := (Vector1^.Y * Vector2^.Z) - (Vector1^.Z * Vector2^.Y);
VectRes^.Y := (Vector1^.Z * Vector2^.X) - (Vector1^.X * Vector2^.Z);
VectRes^.Z := (Vector1^.X * Vector2^.Y) - (Vector1^.Y * Vector2^.X);
end;

function le_CrossVector(Vector1, Vector2: TVector): TVector; overload;
begin
result.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
result.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
result.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;

procedure le_CrossVector(var Vector1, Vector2, VectRes: TVector); overload;
begin
VectRes.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
VectRes.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
VectRes.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;

var
a,b,c: TVector;
i,g: integer;

begin
g :=0;
i := 0;
g:=GetTickCount;
for i:=0 to 1000000000 do le_CrossVector(b,c,a);
writeln(GetTickCount-g);
writeln;

g := 0;
i := 0;
g:=GetTickCount;
for i:=0 to 1000000000 do le_CrossVector(b,c);
writeln(GetTickCount-g);

readln;
end.
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение SovNarKom » 29.06.2005 20:43:49

Четвёртая строчка снизу! Напиши a:=le_CrossVector(b,c);
Ты в Delphi7?

А с указателями у тебя
Код: Выделить всё
g:=GetTickCount;
for i:=0 to 1000000000 do le_CrossVector(b,c,a);
writeln(GetTickCount-g);


хотя быстрее в delphi 5 (!) но не в 6
Код: Выделить всё
g:=GetTickCount;
for i:=0 to 1000000000 do le_CrossVector(@b,@c,@a);
writeln(GetTickCount-g);
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Sniper » 29.06.2005 21:01:21

Если поставить
le_CrossVector1(@b,@c,@a);
le_CrossVector2(b,c);
le_CrossVector3(b,c,a);
Код: Выделить всё
procedure le_CrossVector1(Vector1, Vector2, VectRes: pTVector);
begin
VectRes^.X := (Vector1^.Y * Vector2^.Z) - (Vector1^.Z * Vector2^.Y);
VectRes^.Y := (Vector1^.Z * Vector2^.X) - (Vector1^.X * Vector2^.Z);
VectRes^.Z := (Vector1^.X * Vector2^.Y) - (Vector1^.Y * Vector2^.X);
end;

function le_CrossVector2(Vector1, Vector2: TVector): TVector;
begin
result.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
result.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
result.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;

procedure le_CrossVector3(var Vector1, Vector2, VectRes: TVector);
begin
VectRes.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
VectRes.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
VectRes.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;

результаты забега
34969
36656
15156

И как это понимать? (Delphi7)
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение SovNarKom » 29.06.2005 21:11:48

2,3 - OK.
А вот первое - ???!!! Этого не может быть... :)
а у тебя как FPC?

DELPHI6
8312
21516
8218
А в Delphi5 (1 меняется с 3) но это был баг, я вспомнил. D6 - лучше с указателями.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение SovNarKom » 29.06.2005 21:19:51

Вот FPC 2.0.0 -S2cgi -Og3ru -CX -Xs -XX
15891
79968
14344

Вот FPC 1.9.8(Lazarus 0.9.6) -S2cgi -CX -OG3rp3 -gl -Xs -XX -vewnhi -l
15687
26875
14844
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Sniper » 29.06.2005 21:35:59

Теперь всё впорядке ( моя ошибка была =)

Только объясни PLZ почему:
Код: Выделить всё
procedure le_CrossVector3(var Vector1, Vector2, VectRes: TVector);
begin
VectRes.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
VectRes.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
VectRes.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;

работает также быстро как и первая?

чё-то у меня не работает под FPC
Код: Выделить всё
type
PTVector = ^TVector;
TVector = {packed} record
x, y, z: single;
end;

function le_CrossVector1(Vector1, Vector2: pTVector): pTVector;
begin
Result^.X := (Vector1^.Y * Vector2^.Z) - (Vector1^.Z * Vector2^.Y);
Result^.Y := (Vector1^.Z * Vector2^.X) - (Vector1^.X * Vector2^.Z);
Result^.Z := (Vector1^.X * Vector2^.Y) - (Vector1^.Y * Vector2^.X);
end;

var
a,b,c: TVector;
i,g: integer;

begin
g := 0;
i := 0;
g:=GetTickCount;
for i:=0 to 1000000000 do le_CrossVector1(@b,@c);
writeln(GetTickCount-g);

а так хочется именно функцию, А НЕ процедуру!
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение SovNarKom » 29.06.2005 23:51:30

Sniper
Не работает, так как Result - разрушается после выхода из процедуры, а указатель - остаётся.


Только объясни PLZ почему:

Код: Выделить всё
procedure le_CrossVector3(var Vector1, Vector2, VectRes: TVector);
begin
VectRes.X := (Vector1.Y * Vector2.Z) - (Vector1.Z * Vector2.Y);
VectRes.Y := (Vector1.Z * Vector2.X) - (Vector1.X * Vector2.Z);
VectRes.Z := (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X);
end;


работает также быстро как и первая?


скорее всего из-за автоматической оптимизации у меня Delphi6
8125
27000

а так хочется именно функцию, А НЕ процедуру!


Дык ыть operator ... должен помогать

Примерно так
Код: Выделить всё
operator ** (Va,Vb : TVector) Vc: TVector;
 begin
  Vc.X := (Va.Y * Vb.Z) - (Va.Z * Vb.Y);
  Vc.Y := (Va.Z * Vb.X) - (Va.X * Vb.Z);
  Vc.Z := (Va.X * Vb.Y) - (Va.Y * Vb.X);
 end;


Но я ппока не пробовал :) Щаа...
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение SovNarKom » 30.06.2005 00:11:28

Даа... 25812
Или
Код: Выделить всё
operator ** (Va,Vb : pTVector) Vc: TVector;
begin
 Vc.X := (Va^.Y * Vb^.Z) - (Va^.Z * Vb^.Y);
 Vc.Y := (Va^.Z * Vb^.X) - (Va^.X * Vb^.Z);
 Vc.Z := (Va^.X * Vb^.Y) - (Va^.Y * Vb^.X);
end;

16201 при этом вызов
Код: Выделить всё
a:=@b**@c;
. мдя...

После недолгих размышлений
Код: Выделить всё
operator ** (var Va,Vb : TVector): TVector;
begin
 Result.X := (Va.Y * Vb.Z) - (Va.Z * Vb.Y);
 Result.Y := (Va.Z * Vb.X) - (Va.X * Vb.Z);
 Result.Z := (Va.X * Vb.Y) - (Va.Y * Vb.X);
end;
Жаль, что оператор "^" оверлоадить нельзя... и жаль, что медленней процедуры, хотя быстрее функции.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Sniper » 30.06.2005 00:21:45

Блин, какА всё сложно! =)
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение SovNarKom » 30.06.2005 12:29:19

Короче лучший результат -Rintel -S2cgim -CX -OG3rp3 -gl -Xs -XX + добавление inline ко всему, включая оператор.

9719 a:=b**c
6750 le_CrossVector(@a,@b,@c)
14313 a:=le_CrossVector(b,c)
6140 le_CrossVector(b,c,a)

А смешно то, что просто покрутиться в цикле FPC 2.0.0 3438 а в Delphi6 1100.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Mirage » 28.09.2005 10:42:38

Почему с приставкой var быстрее, чем без оной? Потому что не надо запихивать вектора в стек при передаче параметров. С приставкой const будет также.
Почему процедура быстрее функции? Потому что результат не надо записывать в стек. ;) Функция с var параметрами по идее будет побыстрее, чем с обычными, но самое быстрое - процедура с var параметрами, в чем вы, собственно, и убедились на своем опыте. ;)
Кстати, вроде для SSE надо на 16 байт выравнивать. В Дельфи такого выравнивания нет.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Сообщение pda » 29.09.2005 01:51:38

Mirage писал(а): Почему процедура быстрее функции? Потому что результат не надо записывать в стек. ;)

По моему уже давно все порядочные компиляторы научились возвращаемое значение по возможности в eax оставлять... ;)
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение Mirage » 29.09.2005 07:00:01

Atrus: Да, но EAX для вектора маловат. ;)
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Сообщение pda » 30.09.2005 01:15:06

Atrus: Да, но EAX для вектора маловат.

Вектора и вещественные значения теже компиляторы в st(0) оставляют. ;)
Аватара пользователя
pda
постоялец
 
Сообщения: 303
Зарегистрирован: 27.05.2005 19:59:53

Сообщение Mirage » 30.09.2005 07:09:11

Delphi и FPC тоже так делают? C++'сные (не все) делают. Но они и пустые процедуры удаляют.;)
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 42

Рейтинг@Mail.ru