我正在用F#语言编写raytracer,并且试图在蒙特卡洛采样步骤中使用多线程。
但是,当我使用异步变量运行代码时,该程序永远不会返回并无限期地运行。
我的当前代码:
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
如何使该方法异步递归?
答案 0 :(得分:4)
我找到了问题的原因:
我实际上是从入口点方法Async.RunSynchronously
调用rayTraceBase
的。显然嵌套Async.RunSynchronously
并不是一件好事。在删除第二个Async.RunSynchronously
之后,代码开始工作了。
但是,这非常缓慢,因为到处都会创建异步上下文,并且GC会不停地运行。