I implemented an interactive python loadable module but it requires a heavy computation to do something with the volume. To avoid this heavy computation stuff to block the main slicer app, (after some search) I find one solution is to create a python cli module for this heavy computation stuff and use slicer.cli.run to run it in a threads/process and add an observer to handle the callback?
If that’s the case, I am wondering how could I have a python cli module but do not show in the slicer app window? Basically I just want to call it from my loadble module and do not want the user to reach it through the app.
If there are better solutions to solve the issue, please point them out, thanks!
To give better advice, can you describe what operations are taking the time? I.e. is it tight loops in python or do you call C++ methods (e.g. ITK or VTK)?
This approach could be a good general solution: GitHub - pieper/SlicerProcesses: Slicer modules for running subprocesses to operate on data in parallel
It is basically a deep learning model, so it is written and running purely in python.
But probably the time consuming part is in numpy or other C/C++ code. If you have a bit computation you can release the GIL like we do in SimpleFilters.
We’ll be working on pytorch and monai integration next week as part of project week so we’ll be looking at various integration options and how to best handle the data and computation interactively. You may want to join up.
To be more specific, the time-consuming part is in C (CUDA). Can you provide more information about the GIL, I cannot find it on the project page?
And do you have any idea about the solution I provided in the question? Wrap the time-consuming part as a CLI and run it slicer.cli.run in the background?
Regarding the original question, python is mostly single threaded but long-running calls can release the GIL, which is what we do in SimpleFilters and you could probably do for your CUDA call if the library you are using supports that. Otherwise python threads can’t run at the same time.
There’s a lot of information about it here and here.
If you are using PyTorch, and I guess by extension MONAI, then the long running tasks should be releasing the GIL so you can use threads like in the examples linked above.
I am using PyTorch but not using any MONAI stuff. Oh, so you mean GIL as the python global lock. I can run it in another process instead of thread, so GIL is not a problem. The main problem is that the loadable module’s function will block the main slicer process and freeze the slicer app.
Python CLI is a nice option (we’ll explore alternatives next week).
You can probably change visibility of a CLI module (so that it does not show up in the module finder), but I would not worry about having your CLI module visible to users. Just name it accordingly and place it in a category to make it clear for users that it is an advanced, low-level module. There are many such modules in Slicer. If you want to make your application very simple you would implement a slicelet (and the slicelet would not even have a module selector, so the CLI module would not be visible to the user at all).
Thanks Andras and steve,
I built a python CLI module and it worked perfectly for me!