Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive async method looses its context

I am writing a raytracer in F# and I am trying to use multithreading in the montecarlo sampling step.

However, when I run my code with the async variant, the program never returns and runs indefinitely.

My Code Currently:

let rec rayTrace previousTraceDepth ((ray : Ray) , (accEmitted : Color) , (accScatter :Color)) =
if previousTraceDepth > maxTraceDepth 
then  
    accEmitted + backgroundColor*accScatter
else
    let newTraceDepth = previousTraceDepth + 1us
    let (realSolution,t,surface) = findClosestIntersection ray surfaces
    let surfaceGeometry : Hitable = surface.Geometry
    if surfaceGeometry.IntersectionAcceptable realSolution t 1.0f (PointForRay ray t)
    then
        let emittedShading = surface.Emitted
        let e = accEmitted + accScatter*emittedShading 
        let mcSamples = surface.SampleCount

        //Synchronous
        // let mutable totalShading = e/surface.MCNormalization
        // for _ in 1..mcSamples do
        //     let (doesRayContribute,outRay,cosOfIncidence) = surface.Scatter ray t ((int)newTraceDepth)
        //     let shading = surface.BRDF*cosOfIncidence / (surface.PDF*surface.MCNormalization)
        //     let s = accScatter*shading
        //     totalShading <- totalShading + (rayTrace newTraceDepth (outRay , e , s))
        // totalShading

        let eMCAdjusted = e / surface.MCNormalization
        let shadingSamplesAsync = 
           [|
               for _ in 1..mcSamples -> async {
                       let (doesRayContribute,outRay,cosOfIncidence) = surface.Scatter ray t ((int)newTraceDepth)
                       let shading = surface.BRDF*cosOfIncidence / (surface.PDF*surface.MCNormalization)
                       let s = accScatter*shading
                       return rayTrace newTraceDepth (outRay,e,s)
                   }|]

        if Array.isEmpty shadingSamplesAsync then 
            e
        else
            let shadingSamplesSync = shadingSamplesAsync |> Async.Parallel |> Async.RunSynchronously
            Array.sumBy (fun x -> eMCAdjusted + x) shadingSamplesSync

    else 
       accEmitted + backgroundColor*accScatter

How can I make this method async recursive?

like image 293
Marc HPunkt Avatar asked Sep 03 '26 08:09

Marc HPunkt


1 Answers

I found the cause of the problem:

I was actually calling Async.RunSynchronously from the entry point method i.e rayTraceBase. Apparently nested Async.RunSynchronously is not a good thing. After I removed the second Async.RunSynchronously the code worked.
But it is painfully slow since async contexts are created all over the place and the GC runs non stop.

like image 84
Marc HPunkt Avatar answered Sep 05 '26 17:09

Marc HPunkt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!