Question: Cuda/Futhark (GPU) image manipulation functions in Monomer, Best Practices
Closed this issue · 4 comments
I'm trying to use Cuda/Futhark image manipulation functions in a Monomer App.
Normally I do this by keeping everything in the same Monad that holds the cuda context as part of it's state but in monomer I can only execute a Task on IO asynchronously.
What is the best design pattern for a monomer program that needs to access a cuda context?
Unfortunately, the obvious answer of creating new contexts, besides one inital one, is too slow.
Thanks for all your help!
UPDATE: I was able to answer my own question with some trial and error, I ended up creating some new recordkeepers used as handlers(CUDAContext, GPUCommand), functions (handleCommand, createHandle) and holding the "GPU context" in a lens (held by app model) which maintains an MVar (Chan GPUCommand); though the secret sauce is a (monad) StateTransformer
Thanks again and very much willing to elaborate if you'd like to write tutorials or a cookbook about using GPU Accelerated Code (CUDA, etc) in Monomer :)
This may not be idiomatic, but when you have something that you initiliaze at the start and then use that for the entire app lifetime, I find a module-level global variable using IORef
much better. The module will only export initialize
and run
functions essentially making the global var private. Of course, in case where you have a lot of env data to pass around, what you did maybe better (or maybe both?).
Hi @MilesLitteral!
I think putting that information in the model is perfectly fine. Alternatively, when I don't want to put that kind of information in the model (mainly because it makes it hard to have the required Eq
instance), I create some sort of Env
type that I pass as the first parameter to handleEvent
and buildUI
. For example:
newtype AppEnv = AppEnv {
_dbServerCtx :: DBServerCtx,
}
handleEvent appEnv wenv node model evt = case evt of
-- I can access dbServerCtx where needed
...
buildUI appEnv wenv model = widgetTree where
-- A child widget may need to receive it as a parameter; otherwise, it can be omitted
...
main :: IO ()
main = do
-- Create any computationally expensive that requires one-time initialization
dbCtx <- makeDbCtx
let appEnv = AppEnv dbCtx
startApp model (handleEvent appEnv) (buildUI appEnv) config
where
config = []
model = ...
I'll close the issue. In case you feel something is missing, please re-open it or create a new one. Thanks!