The first if ( d < dm )
is outside of a critical section and could be the cause of a race condition. It should be removed, since there is already one in the critical section. If your purpose is to avoid going too often in the critical part, then this is not the way to do that (see below). You may have to manually flush dm too (see here for some explanations on #pragma omp flush
).
The distancia
function may also not be thread-safe (i.e. rely on some global variable that cannot be concurrently edited by several threads).
Also, it is normal that the result differ if some values of distance are equal. Since there isn't a rule to specifically treat that case (i.e. take the smallest im
), the index of the first minimum value encountered will be kept: it may not be the same in the serial and parallel versions as the iterations are not done in the same order.
Unless the calculation of the distancia
function is CPU intensive, your code is likely to run slower than a serial code for many reasons. Notably, the synchronization overhead of the critical section and the cache sharing issue with variable dm
.
It is better to use a reduction approach, where each thread computes the minimum of whatever iteration it was given to process, and the global minimum is taken as the smallest local minimum of all threads.
float dm=INFINITY;
int im=-1;
#pragma omp parallel shared(dm,im)
{
// Declare private variables
float d,dmin_thread,imin_thread;
dmin_thread=INFINITY;
imin_thread=-1;
// loop through i
#pragma omp for
for ( i = 0 ; i < nt1 ; i++ ) {
d = some_function(i);
// the following lines operate on thread-private variables
if ( d < dmin_thread) {
dmin_thread= d;
imin_thread= i;
}
}// end for
// Reduction part after the loop has been completed
// The critical section is entered only once by each thread
#pragma omp critical
{
if ( dmin_thread < dm) {
dm = dmin_thread;
im = imin_thread;
}
}//end critical
}//end parallel
if(im==-1)
throw_some_error();
else
do_something_with(im);