diff --git a/Code/BasicFilters/otbUnaryFunctorObjectListFilter.h b/Code/BasicFilters/otbUnaryFunctorObjectListFilter.h index caff14bd21e60f4b3a6325c24854e00ac06accb1..6c9fd37a3ab2930045a369f447d9ff5da9aa523b 100644 --- a/Code/BasicFilters/otbUnaryFunctorObjectListFilter.h +++ b/Code/BasicFilters/otbUnaryFunctorObjectListFilter.h @@ -57,9 +57,6 @@ public: typedef typename TInputList::ConstIterator InputListIterator; typedef typename TOutputList::ConstIterator OutputListIterator; - typedef std::vector<OutputListPointer> OutputListForThreadType; - -// typedef itk::DataObject::Pointer DataObjectPointer; /** Get the functor object. The functor is returned by reference. * (Functors do not have to derive from itk::LightObject, so they do @@ -88,22 +85,15 @@ protected: UnaryFunctorObjectListFilter(); virtual ~UnaryFunctorObjectListFilter() {}; - void GenerateData(void); - /** Multi-threading implementation */ - virtual void BeforeThreadedGenerateData(); virtual void AfterThreadedGenerateData(); /** startIndex and stopIndex represent the indices of the Objects to examine in thread threadId */ - virtual void ThreadedGenerateData(unsigned int startIndex, unsigned int stopIndex,int threadId); + virtual void ThreadedGenerateData(unsigned int startIndex, unsigned int stopIndex, int threadId); - /** Static function used as a "callback" by the MultiThreader. The threading - * library will call this routine for each thread, which will delegate the - * control to ThreadedGenerateData(). */ - static ITK_THREAD_RETURN_TYPE ThreaderCallback( void *arg ); /** Internal structure used for passing image data into the threading library */ struct ThreadStruct @@ -118,7 +108,7 @@ private: void operator=(const Self&); //purposely not implemented FunctorType m_Functor; - OutputListForThreadType m_ObjectListPerThread; + }; } // end namespace otb diff --git a/Code/BasicFilters/otbUnaryFunctorObjectListFilter.txx b/Code/BasicFilters/otbUnaryFunctorObjectListFilter.txx index 7ff0c8d92fb2ed557480acb3086df5c682ae20b6..f3121946697b29dc49a6bbe7c4e8262d20181802 100644 --- a/Code/BasicFilters/otbUnaryFunctorObjectListFilter.txx +++ b/Code/BasicFilters/otbUnaryFunctorObjectListFilter.txx @@ -35,54 +35,6 @@ UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> } - -/** - * GenerateData apply the functor on each element of the list - */ -template <class TInputList, class TOutputList, class TFunction > -void -UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> -::GenerateData(void) -{ - // Call a method that can be overridden by a subclass to perform - // some calculations prior to splitting the main computations into - // separate threads - this->BeforeThreadedGenerateData(); - - // Set up the multithreaded processing - ThreadStruct str; - str.Filter = this; - - // Initializing object per thread - OutputListPointer defaultList; - m_ObjectListPerThread = OutputListForThreadType(this->GetNumberOfThreads(),defaultList); - - - // Setting up multithreader - this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads()); - this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str); - - // multithread the execution - this->GetMultiThreader()->SingleMethodExecute(); - - // Call a method that can be overridden by a subclass to perform - // some calculations after all the threads have completed - this->AfterThreadedGenerateData(); - -} - - - -template <class TInputList, class TOutputList, class TFunction > - void - UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> - ::BeforeThreadedGenerateData() -{ - - this->AllocateOutputs(); - -} - template <class TInputList, class TOutputList, class TFunction > void UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> @@ -90,7 +42,7 @@ UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> { InputListPointer inputPtr = this->GetInput(); - m_ObjectListPerThread[threadId] = OutputListType::New(); + this->m_ObjectListPerThread[threadId] = OutputListType::New(); itk::ProgressReporter progress(this, threadId, stopIndex-startIndex); @@ -105,7 +57,7 @@ UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> while((count < stopIndex) && (it != inputPtr->End())) { - m_ObjectListPerThread[threadId]->PushBack(m_Functor(it.Get())); + this->m_ObjectListPerThread[threadId]->PushBack(m_Functor(it.Get())); progress.CompletedPixel(); ++it; @@ -122,10 +74,10 @@ template <class TInputList, class TOutputList, class TFunction > { // copy the lists to the output OutputListPointer outputPtr = this->GetOutput(); - for (int i=0; i< m_ObjectListPerThread.size(); ++i) + for (int i=0; i< this->m_ObjectListPerThread.size(); ++i) { - for(OutputListIterator it = m_ObjectListPerThread[i]->Begin(); - it != m_ObjectListPerThread[i]->End(); + for(OutputListIterator it = this->m_ObjectListPerThread[i]->Begin(); + it != this->m_ObjectListPerThread[i]->End(); ++it) { outputPtr->PushBack(it.Get()); @@ -135,54 +87,6 @@ template <class TInputList, class TOutputList, class TFunction > } - -template <class TInputList, class TOutputList, class TFunction > - ITK_THREAD_RETURN_TYPE - UnaryFunctorObjectListFilter<TInputList,TOutputList,TFunction> - ::ThreaderCallback( void *arg ) -{ - ThreadStruct *str; - int threadId, threadCount; - unsigned int total,start, stop; - - threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID; - threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads; - str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData); - - total = str->Filter->GetInput()->Size(); - - if (threadId < static_cast<int>(total)) - { - - // Split the adjacency matrix in strip of equal dimension - start = static_cast<unsigned int>( vcl_floor( - total*static_cast<double>(threadId)/static_cast<double>(threadCount)+0.5 - )); - stop = static_cast<unsigned int>(vcl_floor( - total*static_cast<double>(threadId+1)/static_cast<double>(threadCount)+0.5 - )); - if (stop > total) - stop = total; - - // For very small list it might occur that start = stop. In this - // case the vertex at that index will be processed in the next strip. - if(start!=stop) - { - str->Filter->ThreadedGenerateData(start, stop, threadId); - } - } - // else - // { - // otherwise don't use this thread. Sometimes the threads dont - // break up very well and it is just as efficient to leave a - // few threads idle. - // } - - return ITK_THREAD_RETURN_VALUE; -} - - - } // end namespace otb #endif diff --git a/Code/Common/otbObjectListSource.h b/Code/Common/otbObjectListSource.h index bd7254f8a06385876e45a6611e796f3f6a90be4d..b98887140c76492c4fe7b0576ee2a705af6ec547 100644 --- a/Code/Common/otbObjectListSource.h +++ b/Code/Common/otbObjectListSource.h @@ -174,7 +174,7 @@ namespace otb /** Ensure that the output lists are cleared before processing */ virtual void AllocateOutputs(); - /** ObjectListSource can be implemented as a multithreaded filter. + /** ObjectListSource can be implemented as a multithreaded filter. * Therefore, this implementation provides a ThreadedGenerateData() routine * which is called for each processing thread. The output image data is * allocated automatically by the superclass prior to calling @@ -183,9 +183,10 @@ namespace otb * "outputRegionForThread" * * \sa ImageToImageFilter::ThreadedGenerateData(), - * ImageToImageFilter::GenerateData() */ + * ImageToImageFilter::GenerateData() */ virtual void GenerateData(void); + private: ObjectListSource(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented diff --git a/Code/Common/otbObjectListSource.txx b/Code/Common/otbObjectListSource.txx index a9e119df214a86d631937fa9338ac8913b69a37b..2d1a8436c05bdd4aac6299dca98c4e24b9cdd8e5 100644 --- a/Code/Common/otbObjectListSource.txx +++ b/Code/Common/otbObjectListSource.txx @@ -20,6 +20,7 @@ #include "otbObjectListSource.h" #include "itkProgressReporter.h" +#include "otbMath.h" namespace otb { @@ -144,6 +145,7 @@ namespace otb itkExceptionMacro("subclass should override this method!!!"); } + /** * PrintSelf Method */ diff --git a/Code/Common/otbObjectListToObjectListFilter.h b/Code/Common/otbObjectListToObjectListFilter.h index 36ae611477bde288d1f57a8fb4cab3263087fa15..1669bfdcc9d205ed04a32d33f00f411b3484c985 100644 --- a/Code/Common/otbObjectListToObjectListFilter.h +++ b/Code/Common/otbObjectListToObjectListFilter.h @@ -64,6 +64,7 @@ namespace otb typedef itk::DataObject::Pointer DataObjectPointer; + typedef std::vector<OutputListPointer> OutputListForThreadType; virtual void SetInput( const InputListType *input); const InputListType * GetInput(void); @@ -77,6 +78,35 @@ namespace otb /**PrintSelf method */ virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; + virtual void GenerateData(void); + + /** Multi-threading implementation */ + + virtual void BeforeThreadedGenerateData(); + + virtual void AfterThreadedGenerateData() {}; + + virtual int SplitRequestedRegion(int threadId, int threadCount, unsigned int requestedElements, unsigned int& startIndex, unsigned int& stopIndex); + + /** startIndex and stopIndex represent the indices of the Objects + * to examine in thread threadId */ + virtual void ThreadedGenerateData(unsigned int startIndex, unsigned int stopIndex, int threadId); + + /** Static function used as a "callback" by the MultiThreader. The threading + * library will call this routine for each thread, which will delegate the + * control to ThreadedGenerateData(). */ + static ITK_THREAD_RETURN_TYPE ThreaderCallback( void *arg ); + + /** Internal structure used for passing image data into the threading library */ + struct ThreadStruct + { + Pointer Filter; + }; + + /** End Multi-threading implementation */ + + OutputListForThreadType m_ObjectListPerThread; + private: ObjectListToObjectListFilter(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented diff --git a/Code/Common/otbObjectListToObjectListFilter.txx b/Code/Common/otbObjectListToObjectListFilter.txx index 020c309ba6303d3967da0739ccb2185de15431d7..79e8e68fd478f161e79297aeacfce9f5d60e1984 100644 --- a/Code/Common/otbObjectListToObjectListFilter.txx +++ b/Code/Common/otbObjectListToObjectListFilter.txx @@ -60,6 +60,126 @@ namespace otb (this->itk::ProcessObject::GetInput(0) ); } + template <class TInputList, class TOutputList> + int + ObjectListToObjectListFilter<TInputList,TOutputList> + ::SplitRequestedRegion(int threadId, int threadCount, unsigned int requestedElements, unsigned int& startIndex, unsigned int& stopIndex ) + { + startIndex = static_cast<unsigned int>( vcl_floor( + requestedElements*static_cast<double>(threadId)/static_cast<double>(threadCount)+0.5 + )); + stopIndex = static_cast<unsigned int>(vcl_floor( + requestedElements*static_cast<double>(threadId+1)/static_cast<double>(threadCount)+0.5 + )); + if (stopIndex > requestedElements) + stopIndex = requestedElements; + + //Note: check the itkImageSource.txx for the compuration done there. + // for now, there is no requested region for ObjectListFilter, so we don't + // compute anything here. + return threadCount; + } + + + /** + * GenerateData + */ + template <class TInputList, class TOutputList> + void + ObjectListToObjectListFilter<TInputList,TOutputList> + ::GenerateData(void) + { + // Call a method that can be overridden by a subclass to perform + // some calculations prior to splitting the main computations into + // separate threads + this->BeforeThreadedGenerateData(); + + // Set up the multithreaded processing + ThreadStruct str; + str.Filter = this; + + // Initializing object per thread + OutputListPointer defaultList; + this->m_ObjectListPerThread = OutputListForThreadType(this->GetNumberOfThreads(),defaultList); + + + // Setting up multithreader + this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads()); + this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str); + + // multithread the execution + this->GetMultiThreader()->SingleMethodExecute(); + + // Call a method that can be overridden by a subclass to perform + // some calculations after all the threads have completed + this->AfterThreadedGenerateData(); + + } + + + template <class TInputList, class TOutputList> + void + ObjectListToObjectListFilter<TInputList,TOutputList> + ::BeforeThreadedGenerateData(void) + { + this->AllocateOutputs(); + } + + template <class TInputList, class TOutputList> + void + ObjectListToObjectListFilter<TInputList,TOutputList> + ::ThreadedGenerateData(unsigned int startIndex, unsigned int stopIndex,int threadId) + { + // The following code is equivalent to: + // itkExceptionMacro("subclass should override this method!!!"); + // The ExceptionMacro is not used because gcc warns that a + // 'noreturn' function does return + itk::OStringStream message; + message << "itk::ERROR: " << this->GetNameOfClass() + << "(" << this << "): " << "Subclass should override this method!!!"; + itk::ExceptionObject e_(__FILE__, __LINE__, message.str().c_str(),ITK_LOCATION); + throw e_; + + } + + template <class TInputList, class TOutputList> + ITK_THREAD_RETURN_TYPE + ObjectListToObjectListFilter<TInputList,TOutputList> + ::ThreaderCallback( void *arg ) + { + ThreadStruct *str; + int threadId, threadCount; + unsigned int total,start, stop; + unsigned int requestedElements; + + threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID; + threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads; + str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData); + + requestedElements = str->Filter->GetInput()->Size(); + total = str->Filter->SplitRequestedRegion(threadId, threadCount, requestedElements, start, stop); + + if (threadId < static_cast<int>(total)) + { + + // For very small list it might occur that start = stop. In this + // case the vertex at that index will be processed in the next strip. + if(start!=stop) + { + str->Filter->ThreadedGenerateData(start, stop, threadId); + } + } + // else + // { + // otherwise don't use this thread. Sometimes the threads dont + // break up very well and it is just as efficient to leave a + // few threads idle. + // } + + return ITK_THREAD_RETURN_VALUE; + } + + /** * PrintSelf Method */