Multithreaded Mandelbrot Fractal

Below is a multithreaded 8th program that calculates and displays Mandelbrot fractal using 8 threads. Also calculates only half of the image and mirrors the other half. Next version of 8th includes optimized version of power function for complex numbers that is over 100x faster than my ‘c:^’ version used in this program.

I would love to see Java version…

EDIT: I added locking for drawing to guard from freezing the GUI on heavy CPU load. Naturally it slows down threads a little.

Here is a video

needs nk/gui

libbin font/Roboto-Regular.ttf

font/Roboto-Regular.ttf font:new "font1" font:atlas! drop

600 constant WIDTH
600 constant HEIGHT

8 constant NUMTASKS

WIDTH HEIGHT img:new constant buffer

WIDTH 1.5 n:/ 40 n:+ constant x-axis
HEIGHT 2 n:/ constant y-axis
300 constant scale
50 constant iterations

: c:^  \ c n -- c
  >r dup c:abs r@ n:^ swap c:arg
  dup 2 a:close
  0 ( r@ n:* n:cos ) a:op!
  1 ( r> n:* n:sin ) a:op!
  swap >r ( r@ n:* ) a:map c:new rdrop ;
 
nullvar mand-task-ids

: mand-task  \ start-row end-row --
  ( drop
    (  drop
       0 0 c:new "z" t:!

       I x-axis n:- scale n:/
       J y-axis n:- scale n:/
       c:new dup "c" t:!

       c:>ri "y" t:! "x" t:!
       "y" t:@ 2 n:^ "y2" t:!
       "x" t:@ 0.25 n:- 2 n:^ "y2" t:@ n:+
       dup "x" t:@ 0.25 n:- n:+ n:* "y2" t:@ 4 n:/ n:<
       "x" t:@ n:1+ 2 n:^ "y2" t:@ n:+ 0.0625 n:< or !if
         ( "z" t:@ 2 c:^ "c" t:@ c:+ dup "z" t:!
           c:abs 2 n:> if
             765 n:* iterations n:/ dup>r 510 n:> if
               255 255 r> 255 n:mod n:int 255 4 a:close "color" t:!
               break 
             else
               r@ 255 n:> if
                 255 r> 255 n:mod n:int 0 255 4 a:close "color" t:!
                 break
               else
                 r> 255 n:mod n:int 0 0 255 4 a:close "color" t:!
                 break
               then
             then
           else 
             drop
             0 0 0 255 4 a:close "color" t:!
           then
         ) 0 iterations n:1- loop
         buffer lock J I "color" t:@ img:pix! HEIGHT J n:- I "color" t:@ img:pix! unlock drop
       then
    ) 0 WIDTH n:1- loop
  null nk:do
  ) -rot loop ;

: start-tasks
  HEIGHT 2 n:/ NUMTASKS n:/mod 0 >r
  a:new ( r@ third n:r+ r@ n:1- 2 ' mand-task t:task-n a:push ) NUMTASKS n:1- times
  -rot n:+ r> tuck n:+ 2 ' mand-task t:task-n a:push mand-task-ids ! ;

: new-win
  {
    name: "main",
    wide: @WIDTH,
    high: @HEIGHT,
    resizable: true,
    title: "Mandelbrot"
  }
  nk:win ;

: main-render
  {
    title: "mandel",
    bg: "black",
    padding: [0,0],
    flags: [ @nk:WINDOW_NO_SCROLLBAR ]
  }

  nk:begin
    null 1 1 nk:layout-grid-begin
      0 1 0 1 nk:grid nk:rect>local nk:grid-push buffer lock nk:image buffer unlock drop
    nk:layout-grid-end
  nk:end ;

: app:main
  ' start-tasks w:is nk:rendering
  new-win ' main-render -1 nk:render-loop ;

1 Like