Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 10:10 03 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Fractal Images

     Page 2 of 3    
Author Message
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1134
Posted: 08:25am 22 Oct 2015
Copy link to clipboard 
Print this post

I found one _very_ slight improvement. In the lines
IF ( Zr * Zr + Zi * Zi ) >= 4 THEN EXIT FOR
and
Zi = 2 * Zr * Zi + CImagVal
the numerical constants 4 and 2 can be moved into variables, resulting in a whopping ... get ready ... 1/8 second improvement.
Visit Vegipete's *Mite Library for cool programs.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 10:02am 22 Oct 2015
Copy link to clipboard 
Print this post

  vegipete said  ... the numerical constants 4 and 2 can be moved into variables, resulting in a whopping ... get ready ... 1/8 second improvement.


Now that is really surprising as I would have thought a variable-to-value lookup would take longer than 'passing' the actual value

I say this exercise should become a challenge to see who can get the fastest time (without CFunctions)

WW
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 10:16am 22 Oct 2015
Copy link to clipboard 
Print this post

@WW
CPU speed is the default of 100MHz
Removing the variable names for the FOR... NEXT loops shaved another 30 seconds off, bring the time down to 1581 seconds. (The initial time to beat was 1979 seconds).

I have also tried using Zr^2 instead of Zr*Zr. The power operator was slightly slower as expected but not as much difference as I thought. About 30 seconds slower.

Putting multiple statements on the one line made negligible difference.

I haven't tried using short variable names and removing blank spaces yet.

Putting the loops at the start of the code makes no difference. There were big differences in the days of line numbers but not any more.

When passing the lines of code, numbers have to be converted from strings to binary which is why it can be faster to use variables instead of literal numbers.

Jim
VK7JH
MMedit
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 12:08pm 22 Oct 2015
Copy link to clipboard 
Print this post

  vegipete said   Nice, Jim.
On my MM+ with 320x240 ILI9341 screen, your last version takes 286 seconds.

By knocking the variable names off the NEXT statements, it drops to 277.5 seconds.


Ok - this was my 'benchmark' and was indeed what roughly what I was seeing initially for 'Julia' (actually 289.98 seconds)

Have applied all the MMBASIC stream-lining that I can think of and here is the new 'target' to beat: 189.616 seconds.

Set on a 64-pin MM+ with 2.4" ILI9341 TFT (320x240) and the very latest Beta

WW

Note: Only BASIC used - no CFUNCTIONS in sight!
Edited by WhiteWizzard 2015-10-23
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 12:59pm 22 Oct 2015
Copy link to clipboard 
Print this post

  TassyJim said  When passing the lines of code, numbers have to be converted from strings to binary which is why it can be faster to use variables instead of literal numbers.


Thanks Jim!

This seems to be the optimal code (or?):

  Quote  'JULIA.BAS - Draws Julia set fractal images
'by loki
CPU 48 ' for uM2
Dim As Integer MAXIT, COUNT
CLS

'Specify initial values
RealOffset = -1.30
ImaginOffset = -0.95
'------------------------------------------------*
'Set the Julia set constant [eg C = -1.2 + 0.8i]
CR = -0.78
CI = -0.20
'------------------------------------------------*
MAXIT=80 'max iterations
GAP = MM.VRes / MM.HRes
SIZE = 2.50
XDelta = SIZE / MM.HRes
YDelta = (SIZE * GAP) / MM.VRes
HR=MM.HRes-1
VR=MM.VRes-1
Timer=0
For X=0 To HR
CX=X*Xdelta+RealOffset
For Y=0 To VR
Zi=Y*YDelta+ImaginOffset
Zr=CX
For C=0 To MAXIT
If Zr*Zr+Zi*Zi>=4 Then Exit For
nZr=Zr*Zr-Zi*Zi+CR
Zi=2*Zr*Zi+CI
Zr=nZr
Next
Pixel X,Y,(C And 4)*4177920+(C And 2)*32640+(C And 1)*255
Next
Next
Print Timer


It takes 402932ms vs 519688ms for Geoffs original version (uM2@48/2.4 LCD 240x320).

Michael

EDIT:
I hope that Geoff interprets this game not as a criticism! Edited by twofingers 2015-10-23
causality ≠ correlation ≠ coincidence
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 01:22pm 22 Oct 2015
Copy link to clipboard 
Print this post

Hi Michael,

I am 'hooked' on this at the moment and am currently down from an initial 289.978 seconds to 184.895.
So from just under five minutes, to a fraction over 3 minutes. This is on a 64pin MM+ so is not comparable with your timings; however, try these things to see if it improves your timings:
1> Shorten ALL variable names to just a single character
2> In the PIXEL command, replace the 4177920 and 32640 values with % variables
3> multiline statements
4> In the 'Exit For' line, replace >=4 with >3
5> Instead of adding negative numbers (i.e. CR=-0.78, and then nZr=..Zi+CR), replace with nZr=..Zi-CR

All these things shaved off almost two minutes for my 320x240 display!

Let us know how you get on

WW
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 02:31pm 22 Oct 2015
Copy link to clipboard 
Print this post

Hi WW,

I'm now at 363468ms (~70%). Not bad! But the code hurts my eyes!
It's a job for a preprocessor, as Peter (C.) would say, I guess.
'JULIA.BAS - Draws Julia set fractal images
'by loki
CPU 48 ' for uM2
Dim As Integer H, C, W, U
CLS

'Specify initial values
S = -1.30
T = -0.95
'------------------------------------------------*
'Set the Julia set constant [eg C = -1.2 + 0.8i]
D = -0.78
E = -0.20
'------------------------------------------------*
Q=80 'max iterations
GAP = MM.VRes / MM.HRes
SIZE = 2.50
P = SIZE / MM.HRes
O = (SIZE * GAP) / MM.VRes
H=MM.HRes-1
V=MM.VRes-1
W=4177920
U=32640
Timer=0
For X=0 To H:M=X*P+S:For Y=0 To V:J=Y*O+T:R=M
For C=0 To Q:If R*R+J*J>3 Then Exit For
N=R*R-J*J+D:J=2*R*J+E:R=N
Next
Pixel X,Y,(C And 4)*W+(C And 2)*U+(C And 1)*255:Next:Next
Print Timer

EDIT:
  WhiteWizzard said  5> Instead of adding negative numbers (i.e. CR=-0.78, and then nZr=..Zi+CR), replace with nZr=..Zi-CR


That takes 363394ms (again -0.02%)!


Regards
MichaelEdited by twofingers 2015-10-24
causality ≠ correlation ≠ coincidence
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 04:54pm 22 Oct 2015
Copy link to clipboard 
Print this post

twofingers code took 1358 seconds on my MM+ with 7in display

The only change I made was to "If R*R+J*J>3 Then Exit For"
I put it back to "If R*R+J*J>=4 Then Exit For"
R and J are both floats so >3 is not the same as >=4

Jim


VK7JH
MMedit
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 04:18am 23 Oct 2015
Copy link to clipboard 
Print this post

  TassyJim said  R and J are both floats so >3 is not the same as >=4

Are you sure this applies also to the northern hemisphere?
I thought, this only applies in the southern hemisphere. (just kidding )

The result for the corrected code (uM2@48/2.4, LCD 240x320) is 372780ms. I'm curious if there are some more improvements are possible ...


causality ≠ correlation ≠ coincidence
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 05:03am 23 Oct 2015
Copy link to clipboard 
Print this post

Maybe (unable to test it) can squeeze a bit more speed by changing
[code]
For C=0 To Q:If R*R+J*J>=4 Then Exit For
N=R*R-J*J+D:J=2*R*J+E:R=N
[/code]
into
[code]
For C=0 To Q:If R^2+J^2>=4 Then Exit For
N=R^2-J^2+D:J=2*R*J+E:R=N
[/code]

Microblocks. Build with logic.
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 06:13am 23 Oct 2015
Copy link to clipboard 
Print this post

AFAIK Jim has already tried.
  TassyJim said  I have also tried using Zr^2 instead of Zr*Zr. The power operator was slightly slower as expected but not as much difference as I thought. About 30 seconds slower.

Regards
Michael

EDIT:
For X=0 To H:M=X*P+S:For Y=0 To V:J=Y*O+T:R=M
For C=0 To Q:If R^2+J^2>=4 Then Exit For
N=R^2-J^2+D:J=2*R*J+E:R=N
Next

Takes 378374ms.
Edited by twofingers 2015-10-24
causality ≠ correlation ≠ coincidence
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 07:13am 23 Oct 2015
Copy link to clipboard 
Print this post

Ha, i should read the whole thread before doing suggestions. :)
Edited by MicroBlocks 2015-10-24
Microblocks. Build with logic.
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 07:46am 23 Oct 2015
Copy link to clipboard 
Print this post

Ok, i can see one more little optimisation when the calculations made at the start of the Y loop are precalculated.
Now these calculations are done for each X.
First need to dimension an array to hold the values.
[code]
DIM K(MM.Vres)
[/code]
Then fill this array with the right values
[code]
For Y=0 To V:K(Y)=Y*O+T:NEXT
[/code]
and change the loop to use the precalculated values
[code]
For X=0 To H:M=X*P+S:For Y=0 To V:J=K(Y):R=M
[/code]

That should shave of another 0.1% .... i hope.....
Microblocks. Build with logic.
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 08:02am 23 Oct 2015
Copy link to clipboard 
Print this post

Hi MB,

nice try, but this is slower than I expected. Takes 379606ms (compared with 372780ms).
Thanks your assistance!

Michael

causality ≠ correlation ≠ coincidence
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1134
Posted: 08:03am 24 Oct 2015
Copy link to clipboard 
Print this post

Hmm, there seem to be variations based on hardware perhaps. Michael's (TwoFingers) eye hurting code with positive initial values and subtraction instead of addition takes 416188 on my MM+64 with 320x240 ILI9341. (This compares with 363394ms that Michael reports.) Since I haven't got all day, I changed to CPU 100, giving a time of 238858.

Out of curiosity, I changed 'R*R+J*J>=4' to 'R*R+J*J>4'. With floating point values, how often would the result be exactly 4.0? Often enough for a 0.1 second INCREASE in time.

For my last test, I precomputed the colour values and stored them in an array. The result: 5 seconds faster. Waahhoooo! Time on my system: 233861. (And I did include the colour precomputation in the timing.)

'JULIA.BAS - Draws Julia set fractal images
'by loki
CPU 100 ' for uM2
Dim As Integer H, C, W, U
dim as integer B(81)
CLS

'Specify initial values
S = 1.30
T = 0.95
'------------------------------------------------*
'Set the Julia set constant [eg C = -1.2 + 0.8i]
D = -0.78
E = -0.20
'------------------------------------------------*
Q=80 'max iterations
GAP = MM.VRes / MM.HRes
SIZE = 2.50
P = SIZE / MM.HRes
O = (SIZE * GAP) / MM.VRes
H=MM.HRes-1
V=MM.VRes-1
W=4177920
U=32640
Timer=0
for X=1 to 81:B(X)=(X And 4)*W+(X And 2)*U+(X And 1)*255:NEXT
For X=0 To H:M=X*P-S:For Y=0 To V:J=Y*O-T:R=M
For C=0 To Q:If R*R+J*J>=4 Then Exit For
N=R*R-J*J+D:J=2*R*J+E:R=N
Next
Pixel X,Y,B(C):Next:Next
Print Timer

Visit Vegipete's *Mite Library for cool programs.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 10:36am 24 Oct 2015
Copy link to clipboard 
Print this post

  vegipete said  . . . Since I haven't got all day, I changed to CPU 100, giving a time of 238858.


Out of interest, can you run at CPU120?
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 10:40am 24 Oct 2015
Copy link to clipboard 
Print this post

Also; change (x AND 4) and (x AND 2)
to (x AND &b100) and (x AND &b10).

This gave me a further reduction!
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 06:01pm 24 Oct 2015
Copy link to clipboard 
Print this post

  WhiteWizzard said   Also; change (x AND 4) and (x AND 2)
to (x AND &b100) and (x AND &b10).

This gave me a further reduction!

That did not work for me, sorry. But the idea is not bad.

Vegipetes code takes 369077ms (uM2@48/2.4, LCD 240x320). Very good!

WWs code
For X=1 To 81:B(X)=(X And &B100)*W+(X And &B10)*U+(X And 1)*255:Next

takes 369076ms.

and this
For C=0 To Q:B(C)=(C And &B100)*W+(C And &B10)*U+(C And 1)*255:Next
For X=0 To H:M=X*P-S:For Y=0 To V:J=Y*O-T:R=M
For C=0 To Q:If R*R+J*J>=&B100 Then Exit For
N=R*R-J*J+D:J=&B10*R*J+E:R=N
Next
Pixel X,Y,B(C):Next:Next

369018ms! ~50ms better!
Thanks Pete and WW!

Michael


causality ≠ correlation ≠ coincidence
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 09:08pm 24 Oct 2015
Copy link to clipboard 
Print this post

I haven't posted all my 'hints' yet, but am currently at 184,122 ms as the most optimised time on a MM+ and a 2.4" ILI9341 SPI.

However, this is with >3 as opposed to >=4 (which has been pointed out is not technically correct for Floats)! Will be trying in the next 24hrs to correct this . . .
 
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1593
Posted: 07:15am 25 Oct 2015
Copy link to clipboard 
Print this post

Amazing:

This is faster (366517ms)
For C=0 To Q:If R*R+J*J>=4 Then Exit For
N=R*R-J*J+D:J=&B10*R*J+E:R=N
NEXT

than this (369070ms)
For C=0 To Q:If R*R+J*J>=4 Then Exit For
N=R*R-J*J+D:J=2*R*J+E:R=N
NEXT

or this (369017ms)
For C=0 To Q:If R*R+J*J>=&B100 Then Exit For
N=R*R-J*J+D:J=&B10*R*J+E:R=N
NEXT

or this (371571ms)
For C=0 To Q:If R*R+J*J>=&B100 Then Exit For
N=R*R-J*J+D:J=2*R*J+E:R=N

but this is even faster (366011ms)
For C=0 To Q:B(C)=(C And &H4)*W+(C And &H2)*U+(C And 1)*255:Next
For X=0 To H:M=X*P-S:For Y=0 To V:J=Y*O-T:R=M
For C=0 To Q:If R*R+J*J>=&H4 Then Exit For
N=R*R-J*J+D:J=&H2*R*J+E:R=N
Next
Pixel X,Y,B(C):Next:Next

Michael
causality ≠ correlation ≠ coincidence
 
     Page 2 of 3    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025