@snuffles
2019-09-04T03:39:17.000000Z
字数 2271
阅读 1543
roborock
在编译选项里加-fopenmp
或者find openmp target link libraries
头文件中加include "omp.h"
并行执行相同代码段
自动将下面的for循环分成N份,(N为电脑CPU核数),然后把每份指派给一个核去执行,而且多核之间为并行执行。
要求
for循环中的循环变量必须是有符号整形。例如,for (unsigned int i = 0; i < 10; ++i){}会编译不通过;
for循环中终止条件要明确,比较操作符必须是<, <=, >, >=。例如for (int i = 0; i != 10; ++i){}会编译不通过;
for循环中的第三个表达式,必须是整数的加减,并且加减的值必须是一个循环不变量。例如for (int i = 0; i != 10; i = i + 1){}会编译不通过;感觉只能++i; i++; --i; 或i--;
如果for循环中的比较操作为<或<=,那么循环变量只能增加;反之亦然。例如for (int i = 0; i != 10; --i)会编译不通过;
循环必须是单入口、单出口,也就是说循环内部不允许能够达到循环以外的跳转语句,exit除外。异常的处理也必须在循环体内处理。例如:若循环体内的break或goto会跳转到循环体外,那么会编译不通过。
————————————————
版权声明:本文为CSDN博主「billbliss」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/billbliss/article/details/44131591
注意循环的形式
例子:error: invalid controlling predicate
如果迭代器是unordered map
那么终止条件 it != map.end()是不明确的,
因为unordered map的空间不是连续的,不能明确的把for循环分为几个线程来做,所以应该通过吧unordered map的索引提前存储在连续空间中,再利用openmp加速
std::vector<std::shared_ptr<Edge>> edges;
edges.reserve(edges_.size());
//for (auto &edge: edges_) //原有的循环
//把索引存起来
for(const auto edge: edges_){
edges.emplace_back((edge.second));
}
//并行
#pragma omp parallel for num_threads(4)
//整体分成四份,不会过于细碎的并行
for(auto block = 0; block < 4 ; ++block) {
//可控的并行循环
for (auto it = edges.begin() + block; it < edges.end(); it += 4)
{
for num_threads(4)
保护并行的数据
#pragma omp parallel for reduction(+:sum) //归约
#pragma omp critical //线程内互斥的代码段
reduction很方便,但它支持一些基本操作,比如+,-,*,&,|,&&,||等。
有些情况下,我们既要避免race condition,但涉及到的操作又超出了reduction的能力范围。
这就要用到openMP的另一个工具,critical。
执行到critical里面时,要注意有没有其他线程正在里面执行,如果有的话,要等其他线程执行完再进去执行。这样就避免了race condition问题,但显而易见,它的执行速度会变低,因为可能存在线程等待的情况。
ref
omp官网
https://blog.csdn.net/billbliss/article/details/44131591openmp 快速入门 常用技巧 parallel for sections reduction critical
OpenMP 入门教程https://www.cnblogs.com/ospider/p/5265975.html