Closed freckletonj closed 3 years ago
This is one of the ramifications that I unfortunately couldn't go into in the article, but it's an important question. It depends a bit on whether the computation can be run concurrently. If yes, you can use EventClock
http://hackage.haskell.org/package/rhine-0.7.0/docs/FRP-Rhine-Clock-Realtime-Event.html. Also, it depends on whether your computation is slow because it blocks on some device access or because it needs to do heavy calculations. And it depends on what you want to achieve. Is it ok if the computation delays the clock, i.e. do we have to achieve the sample rate?
So maybe you can specify a particular use case, and then I can tell you more precisely what would be the right approach?
In the meanwhile I'm going to throw some ideas around how to achieve roughly what you proposed, maybe it's what you're looking for.
slowComputation >-> emitS' @@ MilliSecond 100
which starts a computation but doesn't fully evaluate the thunk. Then in a separate rhine you have tagS >-> arr force >-> useComputation @@ EventClock
which starts a computation whenever an event (= a thunk) arrives. Then you flow
both rhines in a separate thread. As long as useComputation
doesn't block the whole GHC runtime, the first rhine isn't influenced by the second.concurrently
). Then the computation blocks the consumption of the next clock tick, and this will be reflected in the measured timestamps.slowComputation >-> emitS' @@ Busy
in the first thread, which evaluates its argument fully before sending it (And also tries to restart the computation again as soon as the first has finished). Then put tagS >-> (useComputation +++ somethingElseAt10Hz) @@ ParallelClock EventClock (MilliSecond 100)
in the other thread, which is called every 100 ms, and additionally whenever a computation has finished.FixedStep
, and run the computation in there. You can use RescaledClock
to convert the natural number of FixedStep
into e.g. a double, Rational
or UtcTime
.Awesome, that doesn't seem too bad! My usecase was initially just to digest the paper properly, but now knowing this isn't too tough, I may use it in robotics simulation and audio generation!
Thank you, I feel lucky to have this documentation to now refer back to :D
Great :) feel free to come back for any questions. If your use case is open source, feel free to ping me on a PR if you run into trouble, and I can fix it there.
I'll close now. Reopen for further questions.
Ex: a sample rate of 10 Hz, but the intervening computation takes say 3s?
Maybe I missed it in the paper, but I could see 2 solutions:
Realtime solution : a resampling strategy that allows to "ignore clock ticks" if a separate thread is still computing a result from a previous tick. It could interpolate a result for a computation that we didn't have time to actually calculate.
Simulation-time-accurate : A slow computation blocks the entire clock tree. So if you want to simulate 10 x 10Hz samples and each computation takes 3s, the Rhine will take 30s to run, but the result will in-spirit represent 1s of simulation.