c – 使用/为TBB构建分组数据结构

最近我一直在寻找使用TBB而不是boost.threads来加速开发.通常,parallel_for在大多数情况下都有效,但我的情况有点复杂.

有一组结构需要根据成员变量进行排序的计算.这是因为变量值与将在计算期间访问的数据相关,并且根据此分组结构将允许串行设计中的高速缓存一致性.

#include <tbb/tbb.h>
#include <iostream>

struct thing
{
  float value_one;
  float value_two;
  unsigned int sort_id;
};

class functor
{
  thing* m_array;
public:
  functor(thing* _array) : m_array(_array) {;}
  void operator()(const tbb::blocked_range<unsigned int>& r) const
  {
    for(int i = r.begin(); i != r.end(); ++i)
    {
      //Doing a computation with array
      m_array[i].value_one = m_array[i].value_two * m_array[i].value_two;
    }
  }
};

int main(int argc,char const *argv[])
{
  unsigned int n = 10;
  thing* array = new thing[n];

  // Note the ordered id groups
  array[0].sort_id = 1;
  array[1].sort_id = 1;
  array[2].sort_id = 1;
  array[3].sort_id = 2;
  array[4].sort_id = 3;
  array[5].sort_id = 5;
  array[6].sort_id = 5;
  array[7].sort_id = 9;
  array[8].sort_id = 9;
  array[9].sort_id = 9;

  // Do something parallel with array here...
  // parallel_for(tbb::blocked_range<unsigned int>(0,n,2),functor(array));

  delete[] array;

  return 0;
}

上面给出了一个简化的例子,但实际上我很可能有一个大约30-60万个元素的数组.

我知道parallel_for会将数组划分为分组范围.但是我希望每个范围都包含特定id的所有结构.我不介意范围是否包含多个id的结构,只要它们是顺序的并且包含这两个id的所有结构.

int count = 0;
thing** blocks = new thing*[7];
int* sizes = new int[7];

int current_id = 0;
for(unsigned int i = 0; i < n; ++i)
{
  if(array[i].sort_id != current_id)
  {
    current_id = array[i].sort_id;
    blocks[count] = &array[i];
    sizes[count] = 1;
    ++count;
  }
  else
  {
    sizes[count - 1] += 1;
  }
}

parallel_for(tbb::blocked_range<unsigned int>(0,count,functor(blocks,sizes));

我应该以某种方式将数组划分为另一个数组所指向的较小的块然后并行化(如上面的代码所示),如果是这样,那么这样做的有效方法是什么,或者给出最优的示例?是否有一个替代parallel_for(如task_group)更适合这个问题?

解决方法

这个问题对我来说仍然不太清楚,因为你正在混合目标和可能的方法.

如果需要对数组进行排序,则有parallel_sort

如果需要为排序数组构建一个索引,其中sort_id作为键映射到给定元素组在主数组中的索引,请使用concurrent_unordered_map存储组(如果有大量组)和使用parallel_for来构建它.

如果组的数量小于大约数百,则可以使用std :: map或std :: unordered_map并使用parallel_reduce来构造部分映射并将它们合并到最终状态.

最后,当您拥有包含组的正确数据结构时,您可以根据需要在组中使用parallel_for.

附:这个:

grouped ranges called tasks that will be added to the stack for computation

对我来说听起来很奇怪.有一个用户函子(或C 11 lambda)可以并行调用,以处理不同的范围[begin; end].如果你将仿函数称为’任务’,那就没关系,但不要将它与tbb :: task混合.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...