I have a filter that is multithreaded but the time per thread may vary a lot. When I run it, OTB will launch the threads by bunch (depending on the number of CPU available), then it will wait until all the processes end before launching a new bunch. Is it possible to ask the threadedGenerateData to continuously launch threads instead of waitng for the end of a bunch?
I don’t think this is possible with the ITK pipeline framework. To process a block of data (the “Requested Region”),
ITK::ProcessObject::UpdateOutputData does the following (this is simplified !):
- it calls UpdateOutputData on all inputs of the filter.
- it calls
GenerateData(), which in turns (for ImageSource, ImageToImageFilter etc …) :
- Allocates the Output image
- Splits the requested region into N regions, N being the number of threads available
- Spawns N threads and call
ThreadedGenerateData(...)in each thread
- Wait until all threads completed their execution
This means that in a filter, if you override
ThreadedGenerateData, you don’t have much control on how the method is called, by design of the Streaming/Threading mechanism: The process is first streamed, and then threaded, if that makes sense.
If you want to have more control on the streaming, you can override
GenerateData to bypass the ITK threading mechanism and implement threading as required.
I hope that helps,
Thank you Cédric for the explanation. And is there a method to know the number of blocks that will be used (like this->GetNumberOfThreads() but for the number of blocks.
Unlike the number of thread, the number of blocks depends of the pipeline used and is computed by the ImageFileWriter at the end of the pipeline, and more specificaly by the StreamingManager object stored by the ImageFileWriter. You can call the
GetNumerOfSplits() method of the StreamingManager to get the number of blocks that will be used. Note that
PrepareStreming() should be called beforehand.
For instance you could write ;
writer->SetInput(filter->GetOutput()); writer->GenerateOutputInformation(); // This will call PrepareStreaming() on the streaming manager auto numberOfBlocks = writer->GetStreamingManager()->GetNumberOfSplits();
Note that if you want to control the number of splits (instead of having it computed using the RAM) you can use the following methods:
writer->SetNumberOfDivisionsStrippedStreaming(i); // Stripped streaming with i divisions writer->SetNumberOfDivisionsTiledStreaming(i); // Tiled streaming with i divisions writer->SetNumberOfLinesStrippedStreaming(i); // Stripped streaming with i line per strip writer->SetTileDimensionTiledStreaming(i); // Tiled streaming with square tiles of size i x i writer->SetAutomaticTiledStreaming(ram); // RAM driven tiled streaming writer->SetAutomaticStrippedStreaming(ram); // RAM driver stripped streaming writer->SetAutomaticAdaptativeStreaming(ram); // RAM driven tiled streaming that will try to match the TileSize of the input image(s).
You can also use the extended filenames (streaming options).