c++中并行的vector的find_first
find_first of a vector in parallel in C++
我有一个相当大的向量。向量的一些成员平行地匹配某个条件。我想找到第一个符合条件的元素。
我的问题非常类似于这个问题(tbb: parallel find第一个元素),但我没有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
工作共享结构,因为不允许打破并行循环(这就是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循环中使用的critical
结构是昂贵的。如果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
...
}
一旦found
为真,其余的循环迭代将运行"空"体,因为&&
的快捷属性
使用OpenMP,您可以尝试使用#pragma omp for schedule(dynamic)
构建for循环。每个线程将以与vector相同的顺序执行一次迭代。如果你想按线程检查4个元素,试试#pragma omp for schedule(dynamic, 4)
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- OpenMP卸载说'fatal error: could not find accel/nvptx-none/mkoffload'
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 在 QVector<std::unique_ptr 上使用 std::find<Type>>
- 错误"Could not find Boost"(缺少:上下文标头)
- C++算法标头中,为什么要使用 "!(val < *first)" ?
- /usr/bin/ld: cannot find -lc++
- std::find,返回所有找到的值的替代方法,而不仅仅是存在重复的向量的第一个值
- 使用 find 解析文件会给出不同文件的奇怪结果
- 在 ifcondition al中 find() C++ STL 中的 == a.end() 有什么用?
- Cannot find -lglad
- "Cannot find -l<directory>"错误 - CMake
- 为什么在向量上使用 std::find() 时会出现错误?
- 为什么映射插入和 map.find() 的单次迭代比插入和 map.find() 的两次单独迭代慢得多
- C++ find() 在存储为变量时返回不同的值
- set::find 查找不存在的元素
- 使用 std::find 时没有匹配的函数调用错误
- 迭代嵌套映射与范围为循环:没有名为"first"的成员
- C++ 字符串迭代器"find first of"
- 应对"Find the first repeated character in a string"挑战的最紧凑、高效、可读和智能的解决方案