Commit ae8c8f8b authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[ADD] Multithreading implementation has started. ATM there is only a speed up...

[ADD] Multithreading implementation has started. ATM there is only a speed up of 2, meaning you will gain the result in half of time, but it scales unfortunately not very well, so having 15 cores on this job will also result only in the half of the time.. So this clearly need to be reworked.
parent 3633c3ea
......@@ -47,7 +47,7 @@ double& WDXtLookUpTable::operator()( size_t i, size_t j ) throw( WOutOfBounds )
{
std::swap( i, j );
}
return m_data.at( i * m_dim + j - ( i + 1 ) * ( i + 2 ) / 2 );
return m_data[( i * m_dim + j - ( i + 1 ) * ( i + 2 ) / 2 )];
}
size_t WDXtLookUpTable::size() const
......
......@@ -41,6 +41,7 @@
#include "../../common/WLogger.h"
#include "../../common/WProgress.h"
#include "../../common/WStringUtils.h"
#include "../../common/WThreadedFunction.h"
#include "../../dataHandler/datastructures/WFiberCluster.h"
#include "../../dataHandler/exceptions/WDHIOFailure.h"
#include "../../dataHandler/io/WReaderLookUpTableVTK.h"
......@@ -268,9 +269,13 @@ void WMDetTractClustering::cluster()
boost::shared_ptr< WProgress > progress( new WProgress( "Tract clustering", numTracts ) );
m_progress->addSubProgress( progress );
boost::function< double ( const wmath::WFiber& q, const wmath::WFiber& r ) > dLt; // NOLINT
const double proxSquare = proximity_t * proximity_t;
dLt = boost::bind( wmath::WFiber::distDLT, proxSquare, _1, _2 );
if( !m_dLtTableExists )
{
boost::shared_ptr< SimilarityMatrixComputation > threadInstance( new SimilarityMatrixComputation( m_dLtTable, m_tracts, proximity_t * proximity_t, m_shutdownFlag ) );
WThreadedFunction< SimilarityMatrixComputation > threadPool( 2, threadInstance );
threadPool.run();
threadPool.wait();
}
for( size_t q = 0; q < numTracts; ++q ) // loop over all "symmetric" tract pairs
{
......@@ -278,10 +283,6 @@ void WMDetTractClustering::cluster()
{
if( m_clusterIDs[q] != m_clusterIDs[r] ) // both tracts are in different clusters
{
if( !m_dLtTableExists )
{
(*m_dLtTable)( q, r ) = dLt( (*m_tracts)[q], (*m_tracts)[r] );
}
if( (*m_dLtTable)( q, r ) < maxDistance_t ) // q and r provide an inter-cluster-link
{
meld( m_clusterIDs[q], m_clusterIDs[r] );
......@@ -290,6 +291,7 @@ void WMDetTractClustering::cluster()
}
++*progress;
}
progress->finish();
m_dLtTableExists = true;
......@@ -431,3 +433,42 @@ bool WMDetTractClustering::OutputIDBound::accept( boost::shared_ptr< WPropertyVa
{
return ( value >= 0 ) && ( value < static_cast< int >( m_clusters.size() ) );
}
WMDetTractClustering::SimilarityMatrixComputation::SimilarityMatrixComputation(
boost::shared_ptr< WDXtLookUpTable > dLtTable,
boost::shared_ptr< WDataSetFiberVector > tracts,
double proxSquare,
const WBoolFlag& shutdownFlag )
: m_table( dLtTable ),
m_tracts( tracts ),
m_proxSquare( proxSquare ),
m_shutdownFlag( shutdownFlag )
{
}
void WMDetTractClustering::SimilarityMatrixComputation::operator()( size_t id, size_t numThreads, WBoolFlag& b )
{
wlog::debug( "WMDetTractClustering::SimilarityMatrixComputation" ) << "Thread: " << id << " starting its work";
( void ) b; // NOLINT for removing the warning about unused variables
boost::function< double ( const wmath::WFiber& q, const wmath::WFiber& r ) > dLt; // NOLINT
dLt = boost::bind( wmath::WFiber::distDLT, m_proxSquare, _1, _2 );
size_t numTracts = m_tracts->size();
size_t lines = 0;
for( size_t q = 0; q < numTracts && !m_shutdownFlag() ; ++q ) // loop over all "symmetric" tract pairs
{
if( q % numThreads == id )
{
lines++;
for( size_t r = q + 1; r < numTracts; ++r )
{
(*m_table)( q, r ) = dLt( (*m_tracts)[q], (*m_tracts)[r] );
}
}
}
wlog::debug( "WMDetTractClustering::SimilarityMatrixComputation" ) << "Thread: " << id << " done processing " << lines << " lines.";
}
......@@ -216,6 +216,67 @@ private:
private:
const std::vector< WFiberCluster >& m_clusters; //!< accept() need to look into the cluster array for max size constraint
};
/**
* Implements the work each thread has to do, when computing tract
* similarities. This class is intended to work well WThreadedFunction.
*/
class SimilarityMatrixComputation
{
public:
/**
* Creates the environment for the thread, so all data access it will
* need is referenced in this instance.
*
* \note There is no mutex nor locking done for the data each thread
* uses due to two reasons. First, the tracts are read only, and second
* the writing of the results is disjoint which means, that each thread
* will never write at a place where another thread will write to.
*
* \param dLtTable pointer to the similarity matrix
* \param tracts dataset of all tracts
* \param proxSquare the square of the proximity threshold to construct
* the boost::function instance
* \param shutdownFlag a bool flag indicating an abort.
*/
SimilarityMatrixComputation( const boost::shared_ptr< WDXtLookUpTable > dLtTable,
boost::shared_ptr< WDataSetFiberVector > tracts,
double proxSquare,
const WBoolFlag& shutdownFlag );
/**
* Describes the work of each thread. In accordance to each thread \e
* id several rows in the similarity matrix are computed.
*
* \param id Thread ID
* \param numThreads How many threads there are
* \param b Unused here. Since this is an interface we cannot ommit this.
*/
void operator()( size_t id, size_t numThreads, WBoolFlag& b ); // NOLINT
private:
/**
* The table where the similarity computation results should be saved.
*/
boost::shared_ptr< WDXtLookUpTable > m_table;
/**
* Reference to the dataset of the tracts.
*/
boost::shared_ptr< WDataSetFiberVector > m_tracts;
/**
* The Square of the proximity threshold to construct the boost
* function object.
*/
double m_proxSquare;
/**
* This flag is checked during computation serval times to terminate
* all computations incase this is true.
*/
const WBoolFlag& m_shutdownFlag;
};
};
inline const std::string WMDetTractClustering::getName() const
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment