我试着写这段代码
float* theArray; // the array to find the minimum value int index,i; float thisValue,min; index = 0; min = theArray[0]; #pragma omp parallel for reduction(min:min_dist) for (i=1; i<size; i++) { thisValue = theArray[i]; if (thisValue < min) { /* find the min and its array index */ min = thisValue; index = i; } } return(index);
然而,这个没有输出正确的答案.似乎min是正常的,但正确的索引已被线程破坏.
我也尝试过在互联网和这里提供的一些方法(使用并行用于外部循环并使用关键进行最终比较)但这会导致速度下降而不是加速.
我该怎么做才能使最小值及其索引正确?谢谢!
解决方法
我不知道优雅想要做最小的减少和保存索引.我这样做是通过找到每个线程的局部最小值和索引,然后是关键部分中的全局最小值和索引.
index = 0; min = theArray[0]; #pragma omp parallel { int index_local = index; float min_local = min; #pragma omp for nowait for (i = 1; i < size; i++) { if (theArray[i] < min_local) { min_local = theArray[i]; index_local = i; } } #pragma omp critical { if (min_local < min) { min = min_local; index = index_local; } } }
使用OpenMP 4.0,可以使用用户定义的缩减.可以像这样定义用户定义的最小减少量
struct Compare { float val; sizt_t index; }; #pragma omp declare reduction(minimum : struct Compare : omp_out = omp_in.val < omp_out.val ? omp_in : omp_out)
然后可以像这样减少
struct Compare min; min.val = theArray[0]; min.index = 0; #pragma omp parallel for reduction(minimum:min) for(int i = 1; i<size; i++) { if(theArray[i]<min.val) { min.val = a[i]; min.index = i; } }
这适用于C和C.除简化代码外,用户定义的缩减还有其他优点.有多种算法可用于减少.例如,合并可以在O(线程数)或O(Log(线程数))中完成.我给出的第一个解决方案在O(线程数)中执行此操作,但是使用用户定义的缩减,让OpenMP选择算法.