[vtkusers] vtkPointLocator::FindPointsWithinRadius NOT thread safe ?
Jan Ehrhardt
ehrhardt at imi.uni-luebeck.de
Mon Aug 23 03:51:58 EDT 2010
Hi Folks,
we have some trouble using multithreading and
vtkPointLocator::FindPointsWithinRadius(), VTK version 5.4.2.
All is fine, if we run FindPointsWithinRadius() from a single thread.
But running our code in parallel finds incorrect points.
BuildLocator() is called before multithreading.
I include some source code. The code works well with numberOfThreads =
1. If numberOfThreads > 1 lots of Error-Messages "Error: Distance >
Radius: ..." appear.
Thanks for your help,
Jan
void TestMultithreadding( vtkPolyData *surface )
{
mihINFO(" Build point locators ...");
unsigned int numPoints = surface->GetNumberOfPoints();
// build the locator
vtkSmartPointer<vtkPointLocator> spPointLocator =
vtkSmartPointer<vtkPointLocator>::New();
spPointLocator->SetDataSet( surface );
spPointLocator->Initialize();
spPointLocator->BuildLocator();
const unsigned int numberOfThreads = 4;
int ret;
int thr_error = 0;
unsigned int thread_loop;
pthread_t process_id[24];
pthread_attr_t attr;
pthread_attr_init( &attr );
#ifndef __sgi
pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
#endif
mihINFO(" Start Threads ("<<numberOfThreads<<")...");
// Test if for all threads a function is set.
for( thread_loop = 0; thread_loop < numberOfThreads; thread_loop++ )
{
// ==========================================
// Calculate smoothed points.
mihSmoothPointsParameters* forceParameters;
unsigned int threadRange = numPoints / numberOfThreads;
for( unsigned int threadNr = 0; threadNr < numberOfThreads;
++threadNr )
{
// Initialize thread parameters.
forceParameters = new mihSmoothPointsParameters();
// Calculate thread range.
forceParameters->from = threadNr * threadRange;
forceParameters->to = (threadNr == numberOfThreads - 1) ?
numPoints : (threadNr + 1) * threadRange;
// Initializing thread parameters.
forceParameters->surface = surface;
forceParameters->pointLocator = spPointLocator;
forceParameters->numPoints = numPoints;
forceParameters->maxNumOfThreads = numberOfThreads;
forceParameters->threadNum = thread_loop;
if( thread_loop < numberOfThreads - 1 )
{
ret = pthread_create( &(process_id[thread_loop]), &attr,
T_SmoothPoints, (void *) forceParameters );
if( ret != 0 )
{
mihERROR( "Execution of pthread_create failed !" );
}
}
// Start the last thread-method.
else
{
T_SmoothPoints( (void *) forceParameters );
}
}
}
// The parent thread has finished its method - so now it waits for
each of the
// other processes (created with sproc) to exit.
for( thread_loop = 0; thread_loop < numberOfThreads - 1; thread_loop
++ )
{
int ret = pthread_join( process_id[thread_loop], NULL );
if( ret != 0 )
{
mihERROR( "Error waiting for the termination of a thread
(pthread_join)!" );
thr_error = THR_WAIT_ERROR;
}
}
mihINFO(" Finished.");
}
///////////////////////////////////////////////////////////////////////////////////////////
//
// T_SmoothPoints()
//
///////////////////////////////////////////////////////////////////////////////////////////
MIH_THREAD_RETURN_TYPE T_SmoothPoints( void* vargs )
{
mihSmoothPointsParameters* args = (mihSmoothPointsParameters*) vargs;
vtkSmartPointer<vtkPolyData> surface = args->surface;
vtkSmartPointer<vtkPointLocator> pointLocator = args->pointLocator;
const double radius = 5;
double surfacePoint1[3];
double surfacePoint2[3];
double dist2 = 0.0;
// Define neighborhood ID list
vtkIdList *idList = vtkIdList::New();
//std::cout << "From " << args->from << " To " << args->to <<
std::endl;
for( unsigned int i = args->from; i < args->to; ++i )
{
surface->GetPoint( i, surfacePoint1 );
idList->Reset();
pointLocator->FindPointsWithinRadius( radius, surfacePoint1,
idList );
int foundPoints = idList->GetNumberOfIds();
if( foundPoints < 1 )
{
mihERROR( "No Points in Radius " << radius << "found !" );
continue;
}
for( int j = 0; j < foundPoints; j++ )
{
int id = idList->GetId( j );
if( id >= static_cast<int> ( args->numPoints ) || id < 0 )
{
mihERROR( "Invalid Id: " << id );
continue;
}
surface->GetPoint( id, surfacePoint2 );
dist2 = vtkMath::Distance2BetweenPoints( surfacePoint1,
surfacePoint2 );
if( dist2 > radius2 )
{
mihERROR( "Distance > Radius: " << dist2 );
continue;
}
}
}
// Delete the list
idList->Delete();
return MIH_THREAD_RETURN_VALUE;
}
More information about the vtkusers
mailing list