Recent

Author Topic: Too many cycles  (Read 9582 times)

Odigitrium

  • Newbie
  • Posts: 1
Too many cycles
« on: September 22, 2018, 08:52:08 pm »
Hello!

It looks logical and human, but the calculations are not optimal.
Not enough experience and skills to reduce the number of code rows and cycles.
Can you help optimize the procedure?

This is a terrible miracle:

Code: Pascal  [Select][+][-]
  1. procedure TForm.Button1Click(Sender: TObject);
  2. var a, b, c: integer;
  3.                 s:string;
  4.                 ar: array[1..20] of srting;
  5. begin
  6. for a:=1 to 32 do
  7.         for b:=1 to 8765 do
  8.                 for c:=1 to 5673 do
  9.                         if ((a<>c and a<>b and c<>b) and a<21) then
  10.                         begin
  11.                                 s:=floattostr(roundto(a/3,-2))+
  12.                                         inttostr(roundto(b/4,-2)+
  13.                                         floattostr(roundto(c/2,-2));
  14.                                 if ar[a]<>s then ar[a]:=s;
  15.                                 writeln(f1,s);
  16.                         end;
  17. for a:=1 to 20 do
  18.         ar[a]='0';
  19. end;

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Too many cycles
« Reply #1 on: September 22, 2018, 09:05:10 pm »
Why to loop a:=1 to 32 when later is condition ... and (a<21)?

And the code will need fix parenthesis:
Code: Pascal  [Select][+][-]
  1. if ((a<>c and a<>b and c<>b) and a<21) then
  2.  
should be
Code: Pascal  [Select][+][-]
  1. if (((a<>c) and (a<>b) and (c<>b)) and (a<21)) then
  2.  
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: Too many cycles
« Reply #2 on: September 22, 2018, 11:01:34 pm »
This ought to speed it up a little bit while being functionally equivalent:

Code: [Select]
procedure TForm.Button1Click(Sender : TObject);
var i, j, k : Integer;
begin
for i := 1 to   20 do
for j := 1 to 8765 do  if (j <> i)              then
for k := 1 to 5673 do  if (k <> i) and (k <> j) then WriteLn(f1,
        FloatToStr(RoundTo(i / 3, -2) +
        IntToStr  (RoundTo(j / 4, -2) +
        FloatToStr(RoundTo(k / 2, -2)
);
end;

If you need more speed you could divide the workload onto several CPU cores, and stitch it together afterwards.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Too many cycles
« Reply #3 on: September 23, 2018, 07:56:53 am »
Why to loop a:=1 to 32 when later is condition ... and (a<21)?
Probably a spammer trying to pretend to be normal user before changing the original post to something else as had happened here.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Too many cycles
« Reply #4 on: September 23, 2018, 12:24:07 pm »
Can you help optimize the procedure?

If possible, recode without strings. String conversions and operations are the main slowing feature.

to the others: most of the fake spammers post from Thai IPs. This one doesn't, so give him the benefit of the doubt.


Handoko

  • Hero Member
  • *****
  • Posts: 5130
  • My goal: build my own game engine using Lazarus
Re: Too many cycles
« Reply #5 on: September 23, 2018, 12:30:44 pm »
Maybe, the OP really isn't a spammer. But I wonder what kind of the thing he want to achieve using that massive loop.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Too many cycles
« Reply #6 on: September 23, 2018, 04:44:43 pm »
Maybe, the OP really isn't a spammer. But I wonder what kind of the thing he want to achieve using that massive loop.

Build up a table he needs for something else?
The file's gonna be huge though.
[edit]: 994074720 entries...[/edit]
I frequently use fpc to perform such tasks.

Bart
« Last Edit: September 23, 2018, 05:16:43 pm by Bart »

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Too many cycles
« Reply #7 on: September 23, 2018, 04:49:47 pm »
How can you call IntToStr() on the result of RoundTo()?

Bart

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Too many cycles
« Reply #8 on: September 23, 2018, 04:57:46 pm »
give him the benefit of the doubt.

His code does not want to give him that benefit.

8765

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Too many cycles
« Reply #9 on: September 23, 2018, 06:14:27 pm »
Yeah, I'm a little bit crazy.
I did it.

Ditched the FloatToSTr in favor of old fashioned :width:digits notation.
Mad it about 5 times faster.

Code: Pascal  [Select][+][-]
  1. uses
  2.   sysutils, math;
  3. var
  4.   i, j, k, count : Integer;
  5.   f1: text;
  6.   T0, T1, Diff: TDateTime;
  7. begin
  8.   T0 := Now;
  9.   system.assign(f1,'test.txt');
  10.   rewrite(f1);
  11.   count := 0;
  12.   for i := 1 to   20 do
  13.   begin
  14.     for j := 1 to 8765 do
  15.     begin
  16.       if (j <> i) then
  17.       begin
  18.         for k := 1 to 5673 do
  19.         begin
  20.           if (k <> i) and (k <> j) then
  21.           begin
  22.             Inc(count);
  23.             if ((Count mod 100000)=0) then writeln(count);
  24.             WriteLn(f1,
  25.                     {FloatToStr}(RoundTo(i / 3, -2)):4:2,' ',
  26.                     {FloatToStr}(RoundTo(j / 4, -2)):4:2,' ',
  27.                     {FloatToStr}(RoundTo(k / 2, -2)):4:2
  28.             );
  29.  
  30.           end;
  31.         end;
  32.       end;
  33.     end;
  34.   end;
  35.   system.close(f1);
  36.   T1 := Now;
  37.   Diff := T1-T0;
  38.   writeln(count,' items: ',timetostr(Diff));
  39. end.

Code: [Select]
994074720 items: 00:38:55

 Directory of C:\Users\Bart\LazarusProjecten\ConsoleProjecten

23-09-2018  18:06    20.978.705.157 test.txt
               1 File(s) 20.978.705.157 bytes

System:
Intel Core i5-7200@2.7 GHz, with 8GB ram and a SSD harddisk.

Built the program with all runtime checks enabled and optimazation level 1.

Apart from the obvious compiler options: more optimazations in code possible?

PS. Tried to open the resulting file in LibreOffice Writer: it choked on it.

Bart
« Last Edit: September 23, 2018, 06:21:24 pm by Bart »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Too many cycles
« Reply #10 on: September 23, 2018, 06:25:15 pm »
hoist  s:=(RoundTo(i / 3, -2)):4:2,' ',
                    {FloatToStr}(RoundTo(j / 4, -2)):4:2,' ',

out of the inner loop?

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: Too many cycles
« Reply #11 on: September 23, 2018, 09:32:26 pm »
Tried to open the resulting file in LibreOffice Writer: it choked on it.
Try a better text editor: Notepad++, Notepad2, ...

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Too many cycles
« Reply #12 on: September 23, 2018, 11:00:17 pm »
hoist  s:=(RoundTo(i / 3, -2)):4:2,' ',
                    {FloatToStr}(RoundTo(j / 4, -2)):4:2,' ',

out of the inner loop?

Tried that, seems to make no noticable difference.
The bottleneck seems to be file IO.

Bart

guest58172

  • Guest
Re: Too many cycles
« Reply #13 on: September 23, 2018, 11:01:10 pm »
Use a file stream or better (if possible) make everything in memory (memory stream, and preallocates) and use format. Writeln will flush too much.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Too many cycles
« Reply #14 on: September 23, 2018, 11:07:48 pm »
Using SetTextBuf with a buffer of 32K makes the whole thing about 25% faster.
Using TFileStream makes it 3 times slower than with the SetTextBuf adjustment.

Bart
« Last Edit: September 23, 2018, 11:19:43 pm by Bart »

 

TinyPortal © 2005-2018