ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

在C中并行向量的find_first

2019-10-13 03:06:00  阅读:246  来源: 互联网

标签:c multithreading parallel-processing boost openmp


我有一个很大的载体.一些向量成员正在并行匹配某个条件.我想找到与条件匹配的第一个元素.

我的问题与这个问题(tbb: parallel find first element)非常相似,但是我没有tbb.检查条件非常繁琐(因此我无法依次对所有条件进行检查).这就是为什么我想并行运行它.我不得不提到,我想找到第一个元素(因此该元素的索引位置对我来说很重要).

例如,如果我有4个线程.

ThreadNr   Index      condition
1            0         Not Meet
2            1         Not Meet
3            2         Not Meet
4            3         Not Meet

ThreadNr   Index      condition
1            4         Not Meet
2            5          Meet
3            6         Not Meet
4            7          Meet

该函数必须重新调整索引号5.
必须分配线程并在顺序迭代块上工作(块大小可以大于1.例如,线程1处理前4个元素,线程2处理后4个元素,依此类推).

对于上面的示例,如果线程4(在索引7中)在线程2(在索引5中)之前找到成员,则它必须等待所有线程完成作业.正如我之前所说,最低索引号是目标.

如果您有更好的算法,请纠正我.

注意:我可以使用外部库,例如boost 1.62,OpenMP 2.0

解决方法:

由于OpenMP 2.0没有取消构造,因此您必须自己实现一个取消构造,例如,使用共享变量.这也意味着您不能使用for workharing构造,因为不允许打破并行循环(这就是OpenMP 4.0引入取消构造的原因).如果在每个元素的评估之间实施取消检查,则可能会发生两个或多个线程找到与条件匹配的元素.因此,您应该对索引执行最小减少:

int found = 0;
int first_index = INVALID_VALUE;
int iteration = 0;

#pragma omp parallel
{
   int my_index = INVALID_VALUE;
   int i;

   do
   {
      // Later versions of OpenMP allow for "atomic capture"
      // but OpenMP 2.0 requires a critical directive instead
      #pragma omp critical(iteration)
      {
         i = iteration++;
      }

      if (i < N && check(i))
      {
         found = 1;
         my_index = i;
      }
   } while (!found && i < N);

   #pragma omp critical(reduction)
   if (my_index != INVALID_VALUE)
   {
      if (first_index == INVALID_VALUE || my_index < first_index)
         first_index = my_index;
   }

   // Only needed if more code follows before the end of the region
   #pragma omp barrier

   ...
}

此代码假定检查第i个元素的条件(check(i))不会更改元素的状态,因此,可能发生的最坏情况是找到匹配元素的线程可能必须等待让所有其他线程完成检查它们当前正在处理的元素,并且等待时间将是所有处理时间中的最大值.

在do循环中使用的关键构造非常昂贵.如果check()花费的时间不多,那么您可以考虑使用块而不是迭代:

do
{
   #pragma omp critical(chunk)
   {
       my_chunk = chunk++;
   }

   if (my_chunk >= N_chunks)
      break;

   for (i = my_chunk * chunk_size; !found && i < (my_chunk+1)*chunk_size; i++)
   {
      if (check(i))
      {
         found = 1;
         my_index = i;
         break;
      }
   }
} while (!found && my_chunk < N_chunks);

当元素的数量不是那么大并且检查每个元素的代价很高时,另一种效果很好的解决方案:

#pragma omp parallel
{
   #pragma omp for schedule(dynamic,x)
   for (i = 0; i < N; i++)
   {
      if (!found && check(i))
      {
         my_index = i;
         found = 1;
      }
   }

   // Min reduction from the solution above
   ...
}

一旦发现为真,则其余循环迭代将运行“空”主体,因为&&的快捷方式属性.

标签:c,multithreading,parallel-processing,boost,openmp
来源: https://codeday.me/bug/20191013/1905097.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有