Mandelbrot Benchmarking

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

Mandelbrot Benchmarking

Post by drogon »

I decided to update my old Mandelbrot benchmark to the one I used recently (originally in VTL) to check my TinyBasic, then on a whim, I decided to make it work on the other BASICs I had to-hand.

It should work on most retro/8-bit BASIC systems with minimal changes and work over 16-bit signed integer BASICs to 4 or 5 byte floating point ones.

I put it all here:

https://projects.drogon.net/retro-basic ... andelbrot/

Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Mandelbrot Benchmarking

Post by gfoot »

Nice thanks for sharing it - I'm thinking of following your lead and porting BBC BASIC to my system, then maybe I can give it a go!
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Mandelbrot Benchmarking

Post by BigEd »

Nice - thanks for writing up and sharing!

I wonder if there's something funny going on - I'm not 100% happy about the integer-mode output. Of course the problem might be my expectations!

Here's an owlet link for the Beeb running Basic 2
And here's the same thing but using integer arithmetic.
(In both cases, press the rocket button for a quick run.)

I'm suspicious of the shapes of the contours - posting this with a vague idea I might look into it tomorrow.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Mandelbrot Benchmarking

Post by drogon »

BigEd wrote:
I'm suspicious of the shapes of the contours - posting this with a vague idea I might look into it tomorrow.
Me too... I'll translate it to another integer only system tomorrow when I get some time and compare.

Thanks,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Mandelbrot Benchmarking

Post by gfoot »

BigEd wrote:
Nice - thanks for writing up and sharing!

I wonder if there's something funny going on - I'm not 100% happy about the integer-mode output. Of course the problem might be my expectations!
...
I'm suspicious of the shapes of the contours - posting this with a vague idea I might look into it tomorrow.
I had a play with this. Firstly I tried using "DIV" instead of "/" in the floating point version, and the output was not the same. Debugging this revealed that on line 220 the fraction from dividing by F% was affecting the result - i.e. in the integer version, this bit at least was benefiting from "/" being floating point division. So to get a truly integer execution in BBC BASIC, I think you do need to carefully change all the "/" to "DIV", or at least this one!

The real problem however is with the bounds check on lines 230-240:

Code: Select all

230A%=T%: P%=A%/F%:Q%=B%/F%
240IF ((P%*P%)+(Q%*Q%))>=5 GOTO 280
P% and Q% suffer badly from rounding here, as you're dividing by the fixed point factor. You can use floating point for P and Q, or better, do the comparison in the fixed point space:

Code: Select all

230A%=T%
240IF ((A%*A% DIV F%)+(B%*B% DIV F%))>=5*F% GOTO 280
This may suffer different problems if it ends up overflowing the maximum integer width - 16 bits is pretty narrow - I haven't thought much about what the worst-case inputs would be though!

It seems to work pretty well:
https://bbcmic.ro/#%7B%22v%22%3A1%2C%22 ... %5Cn%22%7D
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Mandelbrot Benchmarking

Post by BigEd »

Oh, well done, that does look a lot better!
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Mandelbrot Benchmarking

Post by drogon »

BigEd wrote:
Oh, well done, that does look a lot better!
Also, as an aside, interesting to note than even when presented with all integer variables, BBC Basic still does floating point operations if you're not careful...

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

Re: Mandelbrot Benchmarking

Post by BigEd »

Yes... it does seem to make it a bit more difficult to experiment with the implications of different word sizes.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Mandelbrot Benchmarking

Post by barrym95838 »

gfoot wrote:
The real problem however is with the bounds check on lines 230-240:

Code: Select all

230A%=T%: P%=A%/F%:Q%=B%/F%
240IF ((P%*P%)+(Q%*Q%))>=5 GOTO 280
P% and Q% suffer badly from rounding here, as you're dividing by the fixed point factor. You can use floating point for P and Q, or better, do the comparison in the fixed point space:

Code: Select all

230A%=T%
240IF ((A%*A% DIV F%)+(B%*B% DIV F%))>=5*F% GOTO 280
This may suffer different problems if it ends up overflowing the maximum integer width - 16 bits is pretty narrow - I haven't thought much about what the worst-case inputs would be though!
WOZ BASIC errored out almost immediately with your modification, but was able to render a less accurate version of Gordon's original in about 696 seconds @ 1 MHz:

Code: Select all

  100 REM PR#3 FROM > PROMPT FIRST!
  105 PRINT "MANDELBROT - WOZ BASIC"
  110 PRINT "START"
  130 DIM Z$(17):Z$=".:,;-=+^/%&S$X#@ "
  140 F=50
  150 FOR Y=-12 TO 12
  160 FOR X=-49 TO 29
  170 C=X*229/100
  180 D=Y*416/100
  190 A=C:B=D:I=1
  200 Q=B/F:S=B-Q*F
  210 T=(A*A-B*B)/F+C
  220 B=2*(A*Q+A*S/F)+D
  230 A=T:P=A/F:Q=B/F
  240 IF P*P+Q*Q>4 THEN 280
  250 I=I+1: IF I<17 THEN 200
  280 PRINT Z$(I,I);: NEXT X
  300 PRINT : NEXT Y
  330 PRINT "FINISHED";
  350 END
MAND_WOZ.PNG
MAND_WOZ.PNG (6.59 KiB) Viewed 6293 times
Applesoft renders a much better image, but takes about 860 seconds @ 1 MHz:

Code: Select all

100  REM PR#3 FROM ] PROMPT FIRST!
105  PRINT "MANDELBROT - APPLESOFT"
110  PRINT "START"
130 Z$ = ".:,;-=+^/%&S$X#@ "
140 F = 50
150  FOR Y =  - 12 TO 12
160  FOR X =  - 49 TO 29
170 C = X * 229 / 100
180 D = Y * 416 / 100
190 A = C:B = D:I = 1
200 Q = B / F:S = B - Q * F
210 T = (A * A - B * B) / F + C
220 B = 2 * (A * Q + A * S / F) + D
230 A = T:P = A / F:Q = B / F
240  IF P * P + Q * Q > 4 THEN 280
250 I = I + 1: IF I < 17 THEN 200
280  PRINT  MID$ (Z$,I,1);: NEXT X
300  PRINT : NEXT Y
330  PRINT "FINISHED";
350  END 
MAND_A2+.PNG
MAND_A2+.PNG (6.6 KiB) Viewed 6290 times
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
GlennSmith
Posts: 162
Joined: 26 Dec 2002
Location: Occitanie, France

Re: Mandelbrot Benchmarking

Post by GlennSmith »

Hi,
I was looking for something simple to try out with my rather cumbersome (*) but all the same operational PLASMA Virtual Machine running on the Pico6502. I chose to adapt the Apple][ version that appears above. So the code becomes
[edit] BTW "word" in PLASMA means a 16-bit object.

Code: Select all

byte[] Z = ".:,;-=+^/%&S$X#@ "
word A, B, C, D, E, F, I, P, Q, S, T, X, Y
    F = 50
    for Y = -12 to 12
        for X = -49 to 29
            C = X * 229 / 100
            D = Y * 416 / 100
            A = C; B = D; I = 1
            repeat
                Q = B / F; S = B - Q * F
                T = (A * A - B * B) / F + C
                B = 2 * (A * Q + A * S / F) + D
                A = T; P = A / F; Q = B / F
                if (P * P + Q * Q) > 4 break
                fin
                I++
            until I >= 17
            putc(Z[I])
            next
        putln
    next
    puts("FINISHED\n")
done
... which shows a part of the PLASMA vocabulary. If I run the code through the linux VM, it gives this picture

Code: Select all

......::::::::::::::::::::::,,,,,,,,,;;;;;-=+/S$+^--;;,,,,,,:::::::::::........
.......:::::::::::::::::::::,,,,,,,,,;;;--=%/$  ^^%-;;;;,,,,,:::::::::.........
........::::::::::::::::,,,,,,,,;;;,----==+       %==-;;;;,,:::::::::..........
........:::::::::::,::::,,,,,,,;;;-==++=^^/       %^+==----,,,,::::::..........
.....::::::::::::,,,,,,,,;;;;;;;--=^ &S%              ^/^S=-;,::::::::::.......
...:::::::::::,,,,,,,,,,;;;;;;---++^                       =;,,,,:::::::::.....
....:::::::::::,,,;;;---------===&                       %+--;;,,,:::::::......
.....::::::,,,,,,;;-=X++=^ +===+^%                        &&-;;,,,:::::::......
....::,,,,,,,,;;;;-=+%  /$  #/^/%                          S-;;,,::::::::......
::::::,,,,,,;;;;;-==^/X        #                            -;;,,,::::::::::::.
:::::,,,;;;;-----^/%&                                      =-;;,,:::::::::::::.
::::,,;;--====+=/&                                       $+-;;,,,,,,::::::::::.
::::,                                                   %^=--;;,,,,:::::::::::.
::::,,;;--====+=/&                                       $+-;;,,,,,,::::::::::.
:::::,,,;;;;-----^/%&                                      =-;;,,:::::::::::::.
::::::,,,,,,;;;;;-==^/X        #                            -;;,,,::::::::::::.
....::,,,,,,,,;;;;-=+%  /$  #/^/%                          S-;;,,::::::::......
.....::::::,,,,,,;;-=X++=^ +===+^%                        &&-;;,,,:::::::......
....:::::::::::,,,;;;---------===&                       %+--;;,,,:::::::......
...:::::::::::,,,,,,,,,,;;;;;;---++^                       =;,,,,:::::::::.....
.....::::::::::::,,,,,,,,;;;;;;;--=^ &S%              ^/^S=-;,::::::::::.......
........:::::::::::,::::,,,,,,,;;;-==++=^^/       %^+==----,,,,::::::..........
........::::::::::::::::,,,,,,,,;;;,----==+       %==-;;;;,,:::::::::..........
.......:::::::::::::::::::::,,,,,,,,,;;;--=%/$  ^^%-;;;;,,,,,:::::::::.........
......::::::::::::::::::::::,,,,,,,,,;;;;;-=+/S$+^--;;,,,,,,:::::::::::........
FINISHED
If I run it through the 6502 VM, I get this picture
Picot_6502 Mandelbrot
Picot_6502 Mandelbrot
(*) I can't give any timing for the moment, because the "Pico6502" VM is, in fact, the linux version pushed through cc65 - with stdio and all the rest of it - and it spends 80% of it's time messing around with the C stack and only 20% doing any real work. More news soon on a more "native" 6502 version.
Glenn-in-France
GlennSmith
Posts: 162
Joined: 26 Dec 2002
Location: Occitanie, France

Re: Mandelbrot Benchmarking

Post by GlennSmith »

Hi all,
I have now successfully ported the PLASMA VM to the RP6502 "Picocomputer" in native ASM + Plasma.
It's probably because you're all so far away that I couldn't hear all of the "HOURRAA"s

Anyway, the above code completes in the native VM (bytecode interpreter) in 21.73 seconds. The 65C02 is being clocked at 7.5MHz, 'cos I'm getting fileIO errors at 8MHz. *AND* I had to cheat with the timing, the API entry for reading clock ticks doesn't work currently...

Have a great Sunday y'all.
Glenn-in-France
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Mandelbrot Benchmarking

Post by BigEd »

Hurrah!
resman
Posts: 154
Joined: 12 Dec 2015
Location: Lake Tahoe
Contact:

Re: Mandelbrot Benchmarking

Post by resman »

Hurrah! Can't wait to see what the hybrid VM will do
GlennSmith
Posts: 162
Joined: 26 Dec 2002
Location: Occitanie, France

Re: Mandelbrot Benchmarking

Post by GlennSmith »

resman wrote:
Hurrah! Can't wait to see what the hybrid VM will do
Not sure what you mean... The last result is the "Native" (6502 assembler + Plasma code) VM. No C code at all.
Glenn-in-France
resman
Posts: 154
Joined: 12 Dec 2015
Location: Lake Tahoe
Contact:

Re: Mandelbrot Benchmarking

Post by resman »

GlennSmith wrote:
resman wrote:
Hurrah! Can't wait to see what the hybrid VM will do
Not sure what you mean... The last result is the "Native" (6502 assembler + Plasma code) VM. No C code at all.
When the C coded VM gets compiled for ARM and the byte codes get interpreted from the ARM core as an accelerator. Now you're cooking with gas.
Post Reply