Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Pointer->Integer->Pointer


Страницы:   1 2 3 4 5

alertus ©   (2005-05-27 17:36:00) 

Подскажите, пожалуйста, если я пишу так:

a:^real;
p:^real;
....
getmem(a,100*sizeof(real));
p:=pointer(integer(a)+0);
p^:=0.347;
p:=pointer(integer(a)+8);
p^:=0.764;
p:=pointer(integer(a)+16);
p^:=0.764;
....


Похоже ли это на работу динамического массива и какова будет разница в скорости??


ZlDoc   (2005-05-28 00:09:00) [41]

Народ чет вы все похоже на высоком уровне засиделись (хоть я сам на асьме не профи). Но скажу, что смотреть длинну команды или прогонять Mov в цикле For (да еще и с вызовом процедуры), это както не по научному. имхо.
Время выполнения команды надо тактами процессора измерять (они в старых учебниках по процессорам написаны). Процессор такая вещ что состояние может тока раз в такт менять. Следовательно, чтоб выполнить mov eax, [I + ESP + ECX], ему надо несколько тактов чтоб I + ESP + ECX посчитать, а потом mov выполнить.
Так что и без тестов сказать можно что быстрее выполниться (тем более смотрю никак в результатах не сойдетесь)

PS. Быстрее ассемблера ничего не придумали...


Marser   (2005-05-27 23:50:00) [42]


> Defunct ©   (27.05.05 21:10) [35] [Новое
>сообщение][Ответить]
>begin...end ©   (27.05.05 20:58) [31]
>
> > Ваш код я видоизменил: вместо ламерского способа
> измерения времени выполнения кода функцией использовал
>GetTickCount,
>
> Вам не стыдно такое писать?

Действительно ламерство. Если б ты предложил QueryPerformanceTimer, то это дело. Но TDateTime с сопутствующими - истинная черепаха.
Твоя проблема, ИМХО, в том, что глубочайшие знания у тебя соседствуют с пробелами чуть ли не в табличке умножения.


Defunct   (2005-05-27 23:45:00) [43]

Anatoly Podgoretsky ©   (27.05.05 22:27) [38]

Нет скорее это не влияние цикла вызова и возврата а особенность работы P3, для которого более сложная иструкция (читать более большая), тратит больше времени на погдотовку, потому что за результат [30] я ручаюсь со всей ответственностью.


begin...end ©   (27.05.05 21:37) [36]
Промолчу, если вы заметили, я уже стараюсь с вами не спорить.


begin...end ©   (27.05.05 22:12) [37]

Предполагаю, что на P3 тормозит не умножение индекса, а наличие постоянной константы, которое значительно раздувает размер команды. Для получение объективного результата проверьте в равных условиях команды

mov eax, [I + ESP + ECX*8]
и
mov eax, [I + ESP + ECX]

т.е. сугубо наличие умножения индекса.


Anatoly Podgoretsky   (2005-05-27 22:27:00) [44]

Вот оно влияние цикла, вызова и возврата из подпрограммы. А казалось бы безобидный с виду тест.


begin...end   (2005-05-27 22:12:00) [45]

Воспользовался "методом устранения ошибки" из [30]. Теперь функции содержат по 100 команд MOV: в Test -- команды вида mov eax, [I + ESP + ECX*8], где I -- целочисленные константы от 0 до 99, а в Test2 -- mov eax, [ESP + ECX].

В связи с малой производительностью процессора пришлось уменьшить число итераций до 200 миллионов, иначе я бы заснул в ожидании результатов. А результаты впечатляют:

С умножением  -- 84520
Без умножения -- 46480


"Выводы построите сами" (c) Defunct


begin...end   (2005-05-27 21:37:00) [46]

> Defunct ©   (27.05.05 21:05) [34]

> Я прекрасно знаю насколько объективно, именно Вы относитесь
> к моим постам

Вы своими постами заслужили такое отношение. Поэтому смело можете сказать спасибо зеркалу.

> забыли выключить оптимизацию

Не совсем понятно, каким образом опция оптимизации может повлиять на код самих asm-функций, но, раз уж Вы об этом упомянули, я повторил тест с отключённой оптимизацией.

Результаты таковы:

С умножением  -- 37974
Без умножения -- 34750


Уж и не знаю, что нужно сделать, чтобы вариант с умножением выиграл. Может, с бубном возле компьютера поплясать?

> > Кстати, обратите внимание на количество хинтов компилятора
> Обратил - ни одного hint'a либо warning'a.

Это у Вас что-то с компилятором. А может быть, Вы просто отключили показ хинтов? Приведу список хинтов, возникших на Delphi 7 (конечно, с первого раза код [28] откомпилировать не удалось -- пришлось добавить объявления перменных T1, T2 и T3):

[Hint] Unit1.pas(75): Value assigned to 'T2' never used
[Hint] Unit1.pas(70): Value assigned to 'E2' never used
[Hint] Unit1.pas(67): Value assigned to 'E1' never used
[Hint] Unit1.pas(58): Value assigned to 'T3' never used
[Hint] Unit1.pas(56): Value assigned to 'E2' never used
[Hint] Unit1.pas(54): Value assigned to 'E1' never used


Если выключить оптимизацию, то количество хинтов уменьшается до двух, но они есть.

> Defunct ©   (27.05.05 21:10) [35]

Не стыдно.


Defunct   (2005-05-27 21:10:00) [47]

begin...end ©   (27.05.05 20:58) [31]

> Ваш код я видоизменил: вместо ламерского способа измерения времени выполнения кода функцией использовал GetTickCount,

Вам не стыдно такое писать?


Defunct   (2005-05-27 21:05:00) [48]

begin...end ©   (27.05.05 20:58) [31]

Я прекрасно знаю насколько объективно, именно Вы относитесь к моим постам, но в этот раз ничего у Вас не выйдет. LOL оставьте себе, раз забыли выключить оптимизацию.

> Кстати, обратите внимание на количество хинтов компилятора
Обратил - ни одного hint'a либо warning'a.


alertus   (2005-05-27 21:02:00) [49]

Наваял такую программу:

function writems:string;
var
 t:TDateTime;
 h,m,s,ms:word;
begin
 t:=Time;
 DecodeTime(t, h, m, s, ms);
 result:=inttostr(s)+'.'+inttostr(ms);
end;

procedure TForm1.Button5Click(Sender: TObject);
var
 a:^real;  //311x700
 b:^real;  //700x311
 c:^real;  //311x311
 i,j,k:integer;
 p:^real;
 pa,pb,pc:^real;
 temp:real;
begin
 getmem(a,311*700*sizeof(real));
 getmem(b,311*700*sizeof(real));
 getmem(c,311*311*sizeof(real));

 memo1.lines.add(writems);
 for i:=1 to 311 do begin
   for j:=1 to 311 do begin
     temp:=0;
     p:=integer(0);
     for k:=1 to 700 do begin
       pa:=pointer(integer(a)+(i-1)*311+integer(p));
       pb:=pointer(integer(b)+(j-1)*311+integer(p));
       temp:=temp+pa^*pb^;
       inc(p);
     end;
     pc:=pointer(integer(c)+(i-1+(j-1)*311)*sizeof(real));
     pc^:=temp;
   end;
 end;
 memo1.lines.add(writems);
end;


Время умножения - 1.2 с, прежний метод 3.2 с, метод с использованием a:array[0..0] - 3.0 с (до этого про 4.0 было неверно, я брал другой размер матрицы и перепутал).

т.к. у меня в программе матрица 1 это транспонированная матрица 2, то, я думаю, можно сократить еще время, т.к. у матрицы-результата под нижней диагональю зеркальное отражение того, что над верхней диагональю, но время сократиться еще не более чем в 2 раза.

Очень помогли советы
MBo ©   (27.05.05 18:41) [15] и
begin...end ©   (27.05.05 19:06) [20], всем огромное спасибо.


begin...end   (2005-05-27 20:59:00) [50]


> времени выполнения кода функцией

времени выполнения кода функцией Now


begin...end   (2005-05-27 20:58:00) [51]

> Defunct ©   (27.05.05 19:57) [28]

> тот код который вы приводите я не понимаю

Сорри, но я ничего не могу с этим поделать.

> Это какой-то набор значков.

LOL. Любой листинг программного кода -- это набор значков.

> Не знаю что вы там в нем меряли.

Времена выполнения двух вариантов кода.

Ваш код я видоизменил: вместо ламерского способа измерения времени выполнения кода функцией использовал GetTickCount, хотя это тоже не лучший способ.

var
 i : integer;
 T1, T2, T3: Cardinal;
 E1, E2 : Integer;
begin

 T1 := GetTickCount;

 for i := 0 to 2000*1000*1000 do
 begin
   E1 := Test;
 end;
 E2 := E1;
 T3 := E2*T1;

 T2 := GetTickCount;

 ShowMessage('С умножением: '+ IntToStr(T2 - T1));

 T1 := GetTickCount;

 for i := 0 to 2000*1000*1000 do
 begin
   E1 := Test2;
 end;
 E2 := E1;

 T2 := GetTickCount;

 ShowMessage( 'Без умножения: '+ IntToStr(T2 - T1));

 T2 := E2*T2;

end


Кстати, обратите внимание на количество хинтов компилятора, указывающих на выкинутые им строчки. Это свидетельствует о том, что бессмысленных значков в Вашем коде намного больше, чем в моём.

Результаты проверки таковы (на Pentium 3):

С умножением  -- 30304
Без умножения -- 25947


Чуда не произошло, что мной и ожидалось.


Defunct   (2005-05-27 20:51:00) [52]

Anatoly Podgoretsky ©   (27.05.05 20:12) [29]

Спасибо за метод устранения ошибки.

В общем картина такая.
1. выключил оптимизацию.

2. функция test
приняла такой вид:

xor  ecx, ecx
mov  eax, [0 + ESP + ECX*8]
...
mov  eax, [99 + ESP + ECX*8]

3. Функция test2 такой:
xor  ecx, ecx
mov  eax, [ESP]
...
mov  eax, [ESP]

по сотне команд в обеих функциях. Циклы остались такими же - по 2млрд итераций.


Результаты выполнения теста на P4:

1-й запуск:
с умножением   без умножения
44.581с          44.565с

2-й запуск
с умножением   без умножения
44.518с          44.518с

3-й запуск
с умножением   без умножения
44.518с          44.518с


Выводы постоите сами ;>


Anatoly Podgoretsky   (2005-05-27 20:12:00) [53]

Чего результаты то не привел, ну зачем же каждому компилировать. Кроме того тест желательно оптимизировать, что бы уменьши погрешность от цикла и команд вызова/возврата. это делается так

mov  eax, [ESP + ECX*8]
... повторения строки от 100 раз и более
mov  eax, [ESP + ECX*8]


Defunct   (2005-05-27 19:57:00) [54]

begin...end ©   (27.05.05 19:53) [26]

Да я уже проверил, а тот код который вы приводите я не понимаю. Это какой-то набор значков. Не знаю что вы там в нем меряли.

function test:integer;
var
  a : array[0..100] of byte;
asm
 xor  ecx, ecx
 mov  eax, [ESP + ECX*8]
end;

function test2:integer;
var
  a : array[0..100] of byte;
asm
 xor  ecx, ecx
 mov  eax, [ESP + ECX]
end;

procedure TForm1.rClick(Sender: TObject);
var
 i : integer;
 E1, E2 : Integer;
begin

 T1 := Now;

 for i := 0 to 2000*1000*1000 do
   begin
      E1 := Test;
   end;
   E2 := E1;

 T3 := E2*T1;
 T2 := Now;

 ShowMessage('С умножением '+ FormatDateTime('nn:ss:zzz', T2 - T1));

 T1 := Now;

 for i := 0 to 2000*1000*1000 do
   begin
      E1 := Test2;
   end;

   E2 := E1;
 T2 := Now;

 ShowMessage( 'Без умножения '+ FormatDateTime('nn:ss:zzz', T2 - T1));

 T2 := E2*T2;

end;


Defunct   (2005-05-27 19:55:00) [55]

> begin...end
> сколько в облегчении вычисления индексов.

Вот например это вообще теряет смысл, если проц. и так умеет перемножать индексные регистры непосредственно при адресации элемента массива.

т.е. доступно даже такое

mov eax, [CONST + ebx + ecx*8]
и эта команда будет выполняться одинаково быстро с командой
mov eax, [ebx]


begin...end   (2005-05-27 19:53:00) [56]

> Defunct ©   (27.05.05 19:48) [25]

А Вы, надо полагать, уже проверили?

type
 TElemType = Integer;
 PElemType = ^TElemType;
const
 ElemsCount = 10000000;
var
 a: Pointer;
 p: PElemType;
 T1, T2, I: Cardinal;
begin
 GetMem(a, ElemsCount * sizeof(TElemType));
 p := a;
 T1 := GetTickCount;
 for I := 0 to Pred(ElemsCount) do
   PElemType(Integer(p) + I * sizeof(TElemType))^ := 1;
 T1 := GetTickCount - T1;
 p := a;
 T2 := GetTickCount;
 for I := 0 to Pred(ElemsCount) do
 begin
   p^ := 1;
   Inc(p)
 end;
 T2 := GetTickCount - T2;
 Caption := Format('Умножение: %d; сложение: %d', [T1, T2]);
 FreeMem(a)
end.

"Чуешь Тайд?" (c) Defunct


Defunct   (2005-05-27 19:48:00) [57]

begin...end ©   (27.05.05 19:10) [22]

Ну и ничего,
прежде чем сразу спорить возьми и проверь по скорости

mov  eax, [ebx + ecx]
и
mov  eax, [ebx + ecx*8]

оно рульно будет (С) begin...end


alertus   (2005-05-27 19:41:00) [58]

Да, я согласен, я думал, что sizeof(real) тормозит программу, но это как-бы константа, поэтому лучше писать
p:=pointer(integer(a)+sizeof(real));


> begin...end ©   (27.05.05 19:06) [20]

насчет наращивания адреса, похоже, очень дельный совет.

А еще такой вопрос:
если я по очереди обращаюсь к нескольким элементам памяти, зависит ли скорость от расстояния между этими физическими адресами??


Anatoly Podgoretsky   (2005-05-27 19:12:00) [59]

p:=pointer(integer(a) +8 );
Так не допустимо, размер Real не 8, а величина переменная, но даже если бы и постоянно, то это все равно выглядит некрасиво.


begin...end   (2005-05-27 19:10:00) [60]

> Defunct ©   (27.05.05 19:08) [21]

Ну и что? Речь-то не о возможности, а о скорости.


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо