An exercise in benchmark "optimising"...

Let's talk about anything related to the 6502 microprocessor.
Post Reply
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

An exercise in benchmark "optimising"...

Post by drogon »

Recently, my old Benchmark thread saw some activity so I thought I'd try some of the old tricks we used to do to make BASIC programs run faster, as we did back in the day.

But I want to say firstly that this is not too fair - part of the point of my original Mandelbrot benchmark was to keep the source code identical over all platforms, so this really is cheating and I have, perhaps unfairly, taken advantage of some of BBC Basics features (compared to MS Basics, anyway)

I removed all un-needed spaces and joined lines together as much as I could. I used integer% variables where possible and changed all 2-letter variable names into single letters. The resulting code is somewhat hard on the eyes, however it did run faster. Fast enough to make a difference? Yes . Was it worth it? Who knows.

(FYI: Integers in BBC Basic are 32-bits wide and are treated as Integers where possible, but in particular, single letter Integer variables are stored in fixed memory locations to make them ever faster)

My original one runs in 48.2 seconds on my 16Mhz 65C02 system (actually an '816 in emulation mode) running BBC Basic4.

My tweaked version now runs in 39.4 seconds, so almost 10 seconds better. That was a far better improvement than fiddling with IO to try to cater for the potential slow-downs caused by the actual print routines.

So there you go. Draw your own conclusions.... and someone else can run it under MS Basic/EhBASIC as I really don't care for that old BASIC any more. Give me a modern BASIC from 1981 ;-)

Code: Select all

>*ftp get mandel.2.txt
>*exec mandel.2.txt
>100REM A BASIC, ASCII MANDELBROT
>110REM
>120REM This implementation copyright (c) 2019-2021, Gordon Henderson
>130REM
>140REM Permission to use/abuse anywhere for any purpose granted, but
>150REM it comes with no warranty whatsoever. Good luck!
>160REM
>170C$=".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
>180B%=1 : REM Set to 0 if your MID$() indexes from 0.
>190L%=LEN(C$)
>200M=4
>210S=-2.0
>220T=1.25
>230P=2.5
>240Q=-2.5
>250W%=64
>260H%=48
>270J=P/W%
>280U=Q/H%
>290Q%=TIME
>300FORY%=0TOH%:R=Y%*U+T:FORX%=0TOW%:V=X%*J+S:D=0:E=0:A%=B%
>370G=D*D:H=E*E:IFA%>L% GOTO460
>400IF(G+H)>M GOTO460
>410Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:GOTO370
>460PRINT MID$(C$,A%-B%,1);
>470NEXT:PRINT:NEXT
>500PRINT
>510PRINT (TIME - Q%) / 100
>520END
>RUN
............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;/?o[:+==~~~~~'''''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x  <;:+==~~~~~~'''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:#      X/+====~~~~'''
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X      [:++====~~~''
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/      X/;:+++++==~~'
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x     o&//<;:::[[=~~
...,,'''''''''''''''''~~~~~~=====+:;    &O              /[</&/:=~
...,'''''''''''''''''~~~========++:;<                    x    :=~
..,,'''''''''''''''~~=========+++:;/<O                       ;+==
..,'''''''''''''~~~=========++++:< ##                      X<;:+=
..''''''''''~~~~==:/++++++++::::;/x                          [;:=
.,''''''~~~~~~===+:X[;:;; ;;::;;[                             o/=
.,''''~~~~~~~===++;<xXo<<X &<[[[/                             X:+
.'''~~~~~~~=====+::[&         <<&                             /:=
.'~~~~~~~~=====+::;/?          oO                              :=
.'~~~~~~~====++/;[/o                                          [+=
.~~~~~~=++++::;/???X                                         #:+=
.==++:/::+:;;[[o                                             :+==
                                                           &[:+==
.==++:/::+:;;[[o                                             :+==
.~~~~~~=++++::;/???X                                         #:+=
.'~~~~~~~====++/;[/o                                          [+=
.'~~~~~~~~=====+::;/?          oO                              :=
.'''~~~~~~~=====+::[&         <<&                             /:=
.,''''~~~~~~~===++;<xXo<<X &<[[[/                             X:+
.,''''''~~~~~~===+:X[;:;; ;;::;;[                             o/=
..''''''''''~~~~==:/++++++++::::;/x                          [;:=
..,'''''''''''''~~~=========++++:< ##                      X<;:+=
..,,'''''''''''''''~~=========+++:;/<O                       ;+==
...,'''''''''''''''''~~~========++:;<                    x    :=~
...,,'''''''''''''''''~~~~~~=====+:;    &O              /[</&/:=~
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x     o&//<;:::[[=~~
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/      X/;:+++++==~~'
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X      [:++====~~~''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:#      X/+====~~~~'''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x  <;:+==~~~~~~'''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;/?o[:+==~~~~~'''''
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,

     39.37
-Gordon

Ps. I have just tried it under EhBASIC - which doesn't seem to support integer variables with the % symbol... (huh?) and CBM2 BASIC can't handle integer variables in FOR loops by the looks of it....
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

> FORX%=0TOW%:V=X%*J+S

Is there much of a win in adding J to a running total instead of doing a multiplication?

Edit: hmm, most likely barely detectable, as it's not the innermost loop.

Edit: a somewhat horrific transformation would put line 370 at the start of the program (with something to jump over it), so the GOTO which scans from the start of the text will scan less text.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: An exercise in benchmark "optimising"...

Post by drogon »

BigEd wrote:
> FORX%=0TOW%:V=X%*J+S

Is there much of a win in adding J to a running total instead of doing a multiplication?

Edit: hmm, most likely barely detectable, as it's not the innermost loop.

Edit: a somewhat horrific transformation would put line 370 at the start of the program (with something to jump over it), so the GOTO which scans from the start of the text will scan less text.
No - well, not the quick way I've just tried:

Code: Select all

300FORY%=0TOH%:R=Y%*U+T:K=0:FORX%=0TOW%:V=K+S:D=0:E=0:A%=B%
470K=K+J:NEXT:PRINT:NEXT
Time went UP to 39.44 ...

so the extra statement time must be relatively significant...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

Ah, I was thinking more like this:
300FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%

which does seem to show a (small) speedup. (407s on Owlet)
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: An exercise in benchmark "optimising"...

Post by drogon »

BigEd wrote:
Ah, I was thinking more like this:
300FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%

which does seem to show a (small) speedup. (407s on Owlet)
Ah right. Yes - it's a little better.

... And with a few more tweaks, code shuffling I now have it down to 38.12 seconds, but it's no-longer worth anything as a benchmark as it's only runnable on BBC Basic. Ah well!

So-far:

Code: Select all

100REM A BASIC, ASCII MANDELBROT
110REM
120REM This implementation copyright (c) 2019, Gordon Henderson
130REM
140REM Permission to use/abuse anywhere for any purpose granted, but
150REM it comes with no warranty whatsoever. Good luck!
160REM
170C$=".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
180B%=1 : REM Set to 0 if your MID$() indexes from 0.
190L%=LEN(C$)
200M=4
210S=-2.0
220T=1.25
230P=2.5
240Q=-2.5
250W%=64:H%=48
270J=P/W%:U=Q/H%
290Q%=TIME
300FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
370IFA%>L% THEN460
372G=D*D:H=E*E:IFG+H>M THEN460
410Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:GOTO370
460PRINT MID$(C$,A%-B%,1);
470NEXT:PRINT:NEXT
500PRINT
510PRINT (TIME - Q%) / 100
520END
Next thing might be to investigate using REPEAT... UNTIL in-case that's faster than a GOTO (not convinced though!)
Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

Removing the preamble REMs and condensing single-statement lines, to a less-readable 12 line problem, gets the runtime down to 399s on Owlet. I think that's reducing the text-scanning cost of the GOTOs.

I did try another tactic but it had negative benefit.

I think transforming GOTO into a loop will be a win, although it will look increasingly untidy.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: An exercise in benchmark "optimising"...

Post by drogon »

BigEd wrote:
Removing the preamble REMs and condensing single-statement lines, to a less-readable 12 line problem, gets the runtime down to 399s on Owlet. I think that's reducing the text-scanning cost of the GOTOs.

I did try another tactic but it had negative benefit.

I think transforming GOTO into a loop will be a win, although it will look increasingly untidy.
Ah yes. Removing the REMs and squishing the initialisation into less lines and moving them to the end has helped. 37.1 seconds now. Not bad from the original 48.2 seconds.

Code: Select all

160GOTO600
300FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
370IFA%>L% THEN460
372G=D*D:H=E*E:IFG+H>M THEN460
410Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:GOTO370
460PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
500PRINT
510PRINT (TIME - Q%) / 100
520END
600C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5:W%=64:H%=48:J=P/W%:U=Q/H%:Q%=TIME:GOTO300
I think that without re-writing the algorithm we're almost at the limit of BBC Basic. It would probably still work on other BASICs if I removed all the % integer variables (but if anyone wants to do that, do note that there is a Q and a Q% which are different variables...

Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

A quick renumber before I hack:

Code: Select all

   10GOTO80
   20FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   30IFA%>L% THEN60
   40G=D*D:H=E*E:IFG+H>M THEN60
   50Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:GOTO30
   60PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
   70PRINT:PRINT (TIME - Q%) / 100:END
   80C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5:W%=64:H%=48:J=P/W%:U=Q/H%:Q%=TIME:GOTO20
I'd like to remove a GOTO or two. But first reduce the problem for a faster result:

Code: Select all

   10GOTO80
   20FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   30IFA%>L% THEN60
   40G=D*D:H=E*E:IFG+H>M THEN60
   50Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:GOTO30
   60PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
   70PRINT:PRINT (TIME - Q%) / 100:END
   80C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5
   90W%=16:H%=12:J=P/W%:U=Q/H%:Q%=TIME
  100GOTO20
That's 25.15 in owlet.

Can use REPEAT but it's no faster! 25.3
But I can move one of the IFs to an UNTIL and that's faster, at 24.94

Code: Select all

   10GOTO80
   20PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT:GOTO70
   30FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   40REPEAT
   50G=D*D:H=E*E:IFG+H>M UNTIL TRUE:GOTO20
   60Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:UNTIL A%>L%:GOTO20
   70PRINT:PRINT (TIME - Q%) / 100:END
   80C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5
   90W%=16:H%=12:J=P/W%:U=Q/H%:Q%=TIME
  100GOTO30
It is a bit horrific though.

These two versions are much more structured but do a tad more work, unfortunately:

Code: Select all

   10GOTO80
   20FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   30REPEAT
   40G=D*D:H=E*E:IFG+H<=M Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1
   50UNTILG+H>M ORA%>L%
   60PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
   70PRINT:PRINT (TIME - Q%) / 100:END
   80C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5
   90W%=16:H%=12:J=P/W%:U=Q/H%:Q%=TIME
  100GOTO20

Code: Select all

   10GOTO80
   20FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   30REPEAT:G=D*D:H=E*E:Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:UNTILA%>L%ORG+H>M
   60PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
   70PRINT:PRINT (TIME - Q%) / 100:END
   80C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5
   90W%=16:H%=12:J=P/W%:U=Q/H%:Q%=TIME
  100GOTO20
(Of course now we need to put W% and H% back to full-size values)

If we can do something like that, and remove all GOTOs, the preamble can go back in! In fact the GOTO 80 thing shouldn't be needed:

Code: Select all

   10C$=".,'~=+:;[/<&?oxOX# ":B%=1:L%=LEN(C$):M=4:S=-2.0:T=1.25:P=2.5:Q=-2.5
   20W%=16:H%=12:J=P/W%:U=Q/H%:Q%=TIME
   30FORY%=0TOH%:R=Y%*U+T:V=S-J:FORX%=0TOW%:V=V+J:D=0:E=0:A%=B%
   40REPEAT:G=D*D:H=E*E:Z=G-H+V:E=(D+D)*E+R:D=Z:A%=A%+1:UNTILA%>L%ORG+H>M
   50PRINT MID$(C$,A%-B%,1);:NEXT:PRINT:NEXT
   60PRINT:PRINT (TIME - Q%) / 100
(But as noted, this is not the fastest version)
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

I revisited the Mandelbrot, thinking that using integer variables instead of floats we might get a bit of a speed up. And we do! But we have lost a bit of accuracy and so a few characters of the output come out different.

This version runs in 360.2s in owlet.

Modify W% and H% on lines 750 and 760 for a smaller faster result.

Modify S% on line 695 to play with scaling. The idea is that all reals are divided down by S%, and in this form we can add and compare. When we multiply two reals, we have to divide the result by S%. It turns out to be fastest if S% is a power of two - we're doing divides because we have no shifts, but there's still an advantage in dividing by a power of two.

Code: Select all

100GOSUB600
300FORY%=0TOH%:R%=(U*Y%+T)*S%:V=S-J:FORX%=0TOW%:V=V+J:V%=V*S%:D%=0:E%=0:A%=B%
370IFA%>L%THEN460
380J%=D%*D%DIVS%:K%=E%*E%DIVS%:IFJ%+K%>M%ELSEZ%=J%-K%+V%:E%=((D%+D%)*E%)DIVS%+R%:D%=Z%:A%=A%+1:GOTO370
460PRINT MID$(C$,A%-B%,1);
470NEXT:PRINT:NEXT
500PRINT
510PRINT (TIME - Q%) / 100
520END
600MODE0:REM A BASIC, ASCII MANDELBROT
610REM
620REM This implementation copyright (c) 2019-2021, Gordon Henderson
630REM
640REM Permission to use/abuse anywhere for any purpose granted, but
650REM it comes with no warranty whatsoever. Good luck!
660REM
670C$=".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
680B%=1 : REM Set to 0 if your MID$() indexes from 0.
690L%=LEN(C$)
695S%=2^13
700M%=4*S%
710S=-2.0
720T=1.25
730P=2.5
740Q=-2.5
750W%=64/8
760H%=48/8
770J=P/W%
780U=Q/H%
790Q%=TIME
800RETURN
and here's the output

Code: Select all

............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;[?o[:+==~~~~~'''''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x  <;:+==~~~~~~'''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:X      #/+====~~~~'''
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X      [:++====~~~''
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/      X/;:+++++==~~'
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x     o&//<;:::[[=~~
...,,'''''''''''''''''~~~~~~=====+:;    &O              /[</&/:=~
...,'''''''''''''''''~~~========++:;<                    x    :=~
..,,'''''''''''''''~~=========+++:;/<O                       ;+==
..,'''''''''''''~~~=========++++:< ##                      X<;:+=
..''''''''''~~~~==:/++++++++::::;/x                          [;:=
.,''''''~~~~~~===+:X[;:;; ;;::;;[                             o/=
.,'''~~~~~~~~===++;<xXo<<X &<[[[/                             X:+
.'''~~~~~~~=====+::[&         <<&                             /:=
.'~~~~~~~~=====+::;/?          oO                              :=
.'~~~~~~~====++/;[/o                                          [+=
.~~~~~~=++++::;/???#                                         #:+=
.==++:/::+:;;[[o                                             :+==
                                                           &[:+==
.==++:/::+:;;[[o                                             :+==
.~~~~~~=++++::;/???#                                         #:+=
.'~~~~~~~====++/;[/o                                          [+=
.'~~~~~~~~=====+::;/?          oO                              :=
.'''~~~~~~~=====+::[&         <<&                             /:=
.,'''~~~~~~~~===++;<xXo<<X &<[[[/                             X:+
.,''''''~~~~~~===+:X[;:;; ;;::;;[                             o/=
..''''''''''~~~~==:/++++++++::::;/x                          [;:=
..,'''''''''''''~~~=========++++:< ##                      X<;:+=
..,,'''''''''''''''~~=========+++:;/<O                       ;+==
...,'''''''''''''''''~~~========++:;<                    x    :=~
...,,'''''''''''''''''~~~~~~=====+:;    &O              /[</&/:=~
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x     o&//<;:::[[=~~
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/      X/;:+++++==~~'
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X      [:++====~~~''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:X      #/+====~~~~'''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x  <;:+==~~~~~~'''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;[?o[:+==~~~~~'''''
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,

    361.23
>
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: An exercise in benchmark "optimising"...

Post by drogon »

BigEd wrote:
361.23
>
If I scale my FP BBC Basic version from 48 seconds on a 16Mhz system to a 2Mhz system (by multiplying by 8) then it comes to 384 seconds, so Hmmm.. Not that much faster, but I really don't know what the equivalent speed owlett runs at.

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

I found a little bit more to squeeze out - now runs in 355.42s - also no line numbers any more, so no need to hoist the main loop to the top of the code:

Code: Select all

100MODE0:REM A BASIC, ASCII MANDELBROT
110REM
120REM This implementation copyright (c) 2019-2021, Gordon Henderson
130REM
140REM Permission to use/abuse anywhere for any purpose granted, but
150REM it comes with no warranty whatsoever. Good luck!
160REM
170C$=".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
180B%=1 : REM Set to 0 if your MID$() indexes from 0.
190L%=LEN(C$)
195S%=2^13
200M%=4*S%
210S=-2.0
220T=1.25
230P=2.5
240Q=-2.5
250W%=64
260H%=48
270J=P/W%
280U=Q/H%
290Q%=TIME
300FORY%=0TOH%:R%=(U*Y%+T)*S%:V%=(S-J)*S%:FORX%=0TOW%:V%=V%+J*S%:D%=0:E%=0:A%=B%:REPEATIFA%>L%ELSEJ%=D%*D%DIVS%:K%=E%*E%DIVS%:IFJ%+K%<M% Z%=J%-K%+V%:E%=(D%+D%)*E%DIVS%+R%:D%=Z%:A%=A%+1:UNTILFALSE
460UNTILTRUE:PRINT MID$(C$,A%-B%,1);
470NEXT:PRINT:NEXT
500PRINT
510PRINT (TIME - Q%) / 100
520END
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: An exercise in benchmark "optimising"...

Post by BigEd »

Oh dear, a tiny bit more... 354.92 now.

Code: Select all

190L%=LEN(C$)+1
300FORY%=0TOH%:R%=(U*Y%+T)*S%:V%=(S-J)*S%:FORX%=0TOW%:V%=V%+J*S%:D%=0:E%=0:A%=B%:REPEATIFA%<L% J%=D%*D%DIVS%:K%=E%*E%DIVS%:IFJ%+K%<M% Z%=J%-K%+V%:E%=(D%+D%)*E%DIVS%+R%:D%=Z%:A%=A%+1:UNTILFALSE
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: An exercise in benchmark "optimising"...

Post by drogon »

BigEd wrote:
Oh dear, a tiny bit more...

Code: Select all

190L%=LEN(C$)+1
300FORY%=0TOH%:R%=(U*Y%+T)*S%:V%=(S-J)*S%:FORX%=0TOW%:V%=V%+J*S%:D%=0:E%=0:A%=B%:REPEATIFA%<L% J%=D%*D%DIVS%:K%=E%*E%DIVS%:IFJ%+K%<M% Z%=J%-K%+V%:E%=(D%+D%)*E%DIVS%+R%:D%=Z%:A%=A%+1:UNTILFALSE
Nice :)

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Post Reply