Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q: What if a computation is slower than the sample rate? #151

Closed
freckletonj opened this issue Nov 29, 2020 · 3 comments
Closed

Q: What if a computation is slower than the sample rate? #151

freckletonj opened this issue Nov 29, 2020 · 3 comments
Labels

Comments

@freckletonj
Copy link
Contributor

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:

  1. 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.

  2. 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.

@turion
Copy link
Owner

turion commented Nov 29, 2020

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.

  • Idea 1a (Realtime): You have one rhine 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.
  • Idea 1b (Realtime): The same ingredients, but you put both rhines in the same big signal network. The "disadvantage" is that in one rhine, by default all data-processing units are single-threaded. Only the clocks are launched in different threads (e.g. when using concurrently). Then the computation blocks the consumption of the next clock tick, and this will be reflected in the measured timestamps.
  • Idea 2 (Realtime): Put 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.
  • Idea 3 (simulation time): As you suggest, you use a pure clock like 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.

@freckletonj
Copy link
Contributor Author

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

@turion
Copy link
Owner

turion commented Nov 29, 2020

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.

@turion turion closed this as completed Nov 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants