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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With