f# - using Array.Parallel.map for decreasing running time -
hello everyone
i have converted project in c# f# paints mandelbrot set.
unfortunately take around 1 minute render full screen try find ways speed up.
it 1 call take of time:
array.map (fun x -> this.colorarray.[calcz x]) xyarray
xyarray (double * double) []
=> (array of tuple of double)
colorarray array of int32 length = 255
calcz
defined as:
let calcz (coord:double * double) = let maxiterations = 255 let rec calczhelper (xcoord:double) (ycoord:double) // line break inserted (x:double) (y:double) iters = let newx = x * x + xcoord - y * y let newy = 2.0 * x * y + ycoord match newx, newy, iters | _ when math.abs newx > 2.0 -> iters | _ when math.abs newy > 2.0 -> iters | _ when iters = maxiterations -> iters | _ -> calczhelper xcoord ycoord newx newy (iters + 1) calczhelper (fst coord) (snd coord) (fst coord) (snd coord) 0
as use around half of processor capacity idea use more threads , array.parallel.map, translates system.threading.tasks.parallel
now question
a naive solution, be:
array.parallel.map (fun x -> this.colorarray.[calcz x]) xyarray
but took twice time, how can rewrite take less time, or can take other way utilize processor better?
thanks in advance
gorgen
---edit---
function calling calcz
looks this:
let getmatrix = let halfx = double bitmap.pixelwidth * scale / 2.0 let halfy = double bitmap.pixelheight * scale / 2.0 let rect:mandelbrot.rectangle = {xmax = centerx + halfx; xmin = centerx - halfx; ymax = centery + halfy; ymin = centery - halfy;} let size:mandelbrot.size = {x = bitmap.pixelwidth; y = bitmap.pixelheight} let xylist = generatexytuple rect size let xyarray = array.oflist xylist array.map (fun x -> this.colorarray.[calcz x]) xyarray let region:int32rect = new int32rect(0,0,bitmap.pixelwidth,bitmap.pixelheight) bitmap.writepixels(region, getmatrix, bitmap.pixelwidth * 4, region.x, region.y);
generatexytuple:
let generatexytuple (rect:rectangle) (pixels:size) = let xstep = (rect.xmax - rect.xmin)/double pixels.x let ystep = (rect.ymax - rect.ymin)/double pixels.y [for column in 0..pixels.y - 1 row in 0..pixels.x - 1 yield (rect.xmin + xstep * double row, rect.ymax - ystep * double column)]
---edit---
following suggestion kvb (thanks lot!) in comment question, built program in release mode. building in relase mode speeded things.
just building in release took me 50s around 30s, moving in transforms on array happens in 1 pass made around 10 seconds faster. @ last using array.parallel.init brought me on 11 seconds.
what learnt is.... use release mode when timing things , using parallel constructs... 1 more time, have recieved.
--edit--
using sse assember native dll have been able slash time around 12 seconds 1.2 seconds full screen of computational intensive points. unfortunately don't have graphics processor...
gorgen
as aside, looks you're generating array of coordinates , mapping array of results. don't need create coordinate array if use init
function instead of map
: array.parallel.init 1000 (fun y -> array.init 1000 (fun x -> this.colorarray.[calcz (x, y)]))
edit: following may inaccurate: your problem call tiny function million times, causing scheduling overhead overwhelm actual work you're doing. should partition array larger chunks each individual task takes millisecond or so. can use array of arrays call array.parallel.map
on outer arrays , array.map
on inner arrays. way each parallel operation operate on whole row of pixels instead of single pixel.
Comments
Post a Comment