# Running a Module in Parallel

**URL:** <https://discourse.slicer.org/t/running-a-module-in-parallel/12641>\
**Category:** Development\
**Tags:** segmentation, dicom, python, module\
**Created:** [July 20, 2020, 2:12pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641 "2020-07-20T14:12:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 20, 2020, 2:12pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/1 "2020-07-20T14:12:34Z")

</div>

Hello,

I am currently using a python scripted module to run my vertebra segmentation program. The program uses a for loop to segment multiple fiducial points. This process takes a long time to run and I thought that running in parallel would take a shorter time than iterating through a loop. How can I run my program in parallel using python?

@cpinter @Sunderlandkyl @lassoan

---

<div class="post-metadata">

**Author:** ![adamrankin](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/adamrankin/32/155_2.png) [@adamrankin](https://discourse.slicer.org/u/adamrankin)\
**Post date:** [July 20, 2020, 3:41pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/2 "2020-07-20T15:41:51Z")

</div>

Your most likely route is to call into a c++ library from python.

Python scripted module -\> c++ (loadable) module with no GUI -\> set flag when finished processing

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [July 20, 2020, 3:57pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/3 "2020-07-20T15:57:23Z")

</div>

Another option is to start an independent PythonSlicer process and pass over the data it needs. The SlicerProcess module does this using pickle and stdio, making it pretty efficient. The nice thing is that you get a complete slicer python environment with all the same libraries but independent of mrml and the GUI.

> **[GitHub - pieper/SlicerProcesses: redirect for old SlicerProcessing repo](https://github.com/pieper/SlicerProcesses)**
>
> redirect for old SlicerProcessing repo. Contribute to pieper/SlicerProcesses development by creating an account on GitHub.

> [@Thread for uploading data](https://discourse.slicer.org/t/thread-for-uploading-data/10185/14):
>
> The current SlicerProcesses code isn’t set up for progress reporting. There could be lots of ways to do it, Slicer CLI modules use a convention of embedding xml snippets in the output that triggers automatic progress updates in the GUI. Another option would be to set up a connection like OpenIGTLink to pass data. Or one could create a custom network protocol.

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 20, 2020, 7:12pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/5 "2020-07-20T19:12:41Z")

</div>

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 20, 2020, 11:38pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/6 "2020-07-20T23:38:58Z")

</div>

Does anybody know how to do this?

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 21, 2020, 1:20pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/7 "2020-07-21T13:20:23Z")

</div>

So I have opened up a scriptedcli module and I have my function that I would like to copy on to there (the onApplybutton function from the slicer scripted module), how do I effectively transfer this code to my scriptedcli module and then run this with my scripted module?

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 21, 2020, 1:32pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/8 "2020-07-21T13:32:56Z")

</div>

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 21, 2020, 3:42pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/9 "2020-07-21T15:42:06Z")

</div>

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 22, 2020, 2:03pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/11 "2020-07-22T14:03:46Z")

</div>

Hello,

I have a local threshold segmentation code in a scripted python module which iterates through fiducial points and runs the local threshold function. Iterating through points takes a while to do and to speed it up, I would like it to run in parallel with a scripted CLI python module. I have set a list of parameters, and I have this line of code:

slicer.cli.runSync(slicer.modules.climodulecode, None, param, True, True)

I am not sure what to do in terms of adding code to the scripted cli module and how to use the parameters from there. I have looked at some examples but I am still a little unclear.

Thanks

---

<div class="post-metadata">

**Author:** ![vertebrae](https://avatars.discourse-cdn.com/v4/letter/v/dec6dc/32.png) [@vertebrae](https://discourse.slicer.org/u/vertebrae)\
**Post date:** [July 22, 2020, 5:08pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/12 "2020-07-22T17:08:43Z")

</div>

param = {“inputVolume”: masterVolumeNode.GetID(), “MinimumThreshold”: 265, “MaximumThreshold”: 1009, “MinimumDiameterMm”: 9, “Seed”:fidList.getID()}

These are my parameters. Any ideas? @lassoan @pieper

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [July 23, 2020, 1:44am UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/13 "2020-07-23T01:44:44Z")

</div>

`slicer.cli.runSync` blocks execution until processing is complete. `slicer.cli.runAsync` blocks execution until processing is complete. `slicer.cli.run(..., wait_for_completion = False)` is not much better either, as Slicer always runs only one CLI at a time (the only advantage is that you can still use Slicer while computation is running in the background). For parallel execution, I would recommend to use @pieper’s SlicerProcesses extension.

Another approach is to keep a single process but use multiple seeds. LocalThreshold effect uses only a single input point, but you could modify it to take all your input points at once.

However, before you would start trying these, the most important thing is to profile your existing implementation. You need to know what line(s) of code take most of the time and focus only on those. There are Python profilers that you can configure or you can measure approximate execution time by adding log messages.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [April 2, 2022, 12:06pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/14 "2022-04-02T12:06:53Z")

</div>

I would be interested on creating a CLI module (written on C++) for saving selected nodes or all scene (just what the save dialog achieves).  
I think this would be useful since it will allow the user to autosave by executing the callback of a timer periodically and (if I understood correctly) Slicer GUI will not freeze, further more all features (processing and visualization) of Slicer would be available as it is normally.

Would this idea work? Would this idea have a positive impact if it’s implemented?

Thank you

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [April 2, 2022, 2:21pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/15 "2022-04-02T14:21:20Z")

</div>

It it’s a CLI running as a separate process (the default) then Slicer would communicate with it via files and there would be no real time saved. If the saving is in a separate thread there could be a problem if, for example, the data is deleted in the main thread during the save. You could implement a threaded version that copies all the data to private memory in the thread and then does the disk IO while the main thread goes on to other tasks. In fact, you can use multiple threads, say one for each data file and that could speed up, for example, compression. I tried this once for reading and got about 6x performance improvement for a scene with lots of files.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mau_igna_06/32/9056_2.png) [@mau\_igna\_06](https://discourse.slicer.org/u/mau_igna_06)\
**Post date:** [April 2, 2022, 2:35pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/16 "2022-04-02T14:35:16Z")

</div>

So memory cannot be shared between processes even in a read-only mode?  
Maybe you could flag/lock the nodes that are being read so the cannot be modified during the save.  
Could two Slicer instances share RAM and through it share node references so one saves the nodes on the background while the other does visualization of them on the foreground? Maybe on a virtualized enviroment that’s possible?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [April 2, 2022, 2:55pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/17 "2022-04-02T14:55:46Z")

</div>

There’s nothing that locks memory in the scene so sharing it between processes would be unsafe in general (modules can modify the scene contents). Copying in memory is usually a very efficient operation compared to IO so it’s probably the best way to go. It should be easy to try some timing experiments.

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [June 29, 2022, 2:52pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/18 "2022-06-29T14:52:40Z")

</div>

_Documenting here comments reported during the IGT session that took place during the 37th NA-MIC project week related to [SlicerParallelProcessing](https://github.com/pieper/SlicerParallelProcessing)_

from @jcfr

> Why not look into doing a scripted CLI module running in the background ?
> 
> As well as improving the way such module can communicate feedback back to the application

from @cpinter

> Not being able to run algorithms on an actual parallel process in Python was a big limitation. Steve’s module solves this issue, but that doesn’t mean the other options are not available anymore  
> CLI is super flexible in that you only need to specify the command-line and under the hood it van be anything, even python

From @lassoan

> The only current limitation of CLIs is that Slicer runs them on a single background thread, so if you start multiple CLIs they are all executed one after the other on that background thread. On most computers you have 8 or more cores, so allow running 5-10 CLIs in parallel could makes things faster (as demonstrated by ParallelProcessing extension).

cc: @ungi

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [June 29, 2022, 2:53pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/19 "2022-06-29T14:53:25Z")

</div>

> current limitation of CLIs is that Slicer runs them on a single background thread, so if you start multiple CLIs they are all executed one after the other on that background thread

To address this, I started a topic [Commits · jcfr/Slicer · GitHub](https://github.com/jcfr/Slicer/commits/support-running-cli-in-parallel)

---

<div class="post-metadata">

**Author:** ![MJamal](https://avatars.discourse-cdn.com/v4/letter/m/d26b3c/32.png) [@MJamal](https://discourse.slicer.org/u/MJamal)\
**Post date:** [March 2, 2024, 7:33am UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/20 "2024-03-02T07:33:43Z")

</div>

> [@pieper](#):
>
> You could implement a threaded version that copies all the data to private memory in the thread

Apparently, the MRML scene cannot be directly delegated to another thread from the main thread. Therefore, I believe the main thread may still be used for this copy operation to make the scene/data available to other threads.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 10, 2024, 10:30pm UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/21 "2024-03-10T22:30:44Z")

</div>

Yes, while copying the inputs and final outputs from/to the scene the main thread must be blocked (or the main thread must copy the data). Copying can be done by just replacing a few pointers, so the main thread is blocked for just microseconds.

---

<div class="post-metadata">

**Author:** ![MJamal](https://avatars.discourse-cdn.com/v4/letter/m/d26b3c/32.png) [@MJamal](https://discourse.slicer.org/u/MJamal)\
**Post date:** [March 14, 2024, 3:34am UTC](https://discourse.slicer.org/t/running-a-module-in-parallel/12641/22 "2024-03-14T03:34:11Z")

</div>

I’d like to know if the usage of these ‘few pointers’ is dependent on input size.

What I am considering is deep copying the nodes from the main thread, such as segmentation nodes, transformation nodes, color table nodes, etc., except for volume nodes which might be larger, into another thread and then performing the autosave operation. The downside to this approach is that memory overhead will increase as the size of nodes grows.
