openMP的简单使用

安装,参考:https://blog.csdn.net/augusdi/article/details/8808226
如图所示,右键工程名->属性->C/C++->语言,找到OpenMP支持,更改设置即可。
这里写图片描述

代码编程,参考:https://blog.csdn.net/zhongkejingwang/article/details/40350027
在C/C++中使用OpenMP优化代码方便又简单,代码中需要并行处理的往往是一些比较耗时的for循环,所以下面介绍一下OpenMP中for循环的应用。

1. 首先,如何使一段代码并行处理呢?

omp中使用parallel制导指令标识代码中的并行段,形式为:

#pragma omp parallel
{
    ...//每个线程都会执行大括号里的代码
}

我们编写如下的代码:

#include <iostream>
#include "omp.h"
using namespace std;
int main(int argc, char **argv) {
    //设置线程数,一般设置的线程数不超过CPU核心数,这里开4个线程执行并行代码段
    omp_set_num_threads(4);
    #pragma omp parallel
    {
        cout << "Hello" << ", I am Thread " << omp_get_thread_num() << endl;
    }
}

上面的代码输出结果为:

Hello,Thread Hello,Thread 21
Hello,Thread 3
Hello,Thread 0

可以看到四个线程各自独立的输出了cout后面的内容。如果去掉omp_set_num_threads(4)语句,我们的电脑CPU的每个核都会独立执行,我的CPU有8个核,就会执行8次大括号内的语句。

2.带有for的制导指令:

使用形式为:

#pragma omp parallel for
for()

或者

#pragma omp parallel
{   //注意:大括号必须要另起一行
    #pragma omp for
    for()
}

第一种形式作用域只是紧跟着的那个for循环,而第二种形式在整个并行块中可以出现多个for制导指令。

...
#include "omp.h"
...
int main()
{
    omp_set_num_threads(4);
    #pragma omp parallel for
    for (int i = 0; i < 6; i++)
    {
        printf("i = %d,Hello,Thread:%d\n", i, omp_get_thread_num());
    }
    return 0;
}

输出结果如下:

i = 0,Hello,Thread:0
i = 1,Hello,Thread:0
i = 2,Hello,Thread:1
i = 3,Hello,Thread:1
i = 5,Hello,Thread:3
i = 4,Hello,Thread:2

我们可以看到输出6次printf的任务被分给了CPU的4个核。

3.数据同步问题

int main()
{
    int n = 100000;
    int sum = 0;
    omp_set_num_threads(4);
    #pragma omp parallel for
    for (int i = 0; i < n; i++)
    {
        sum++;
    }
    cout << sum << endl;
    return 0;
}

期望的正确结果是100000,但是这样写是错误的。看代码,由于默认情况下sum变量是每个线程共享的,所以多个线程同时对sum操作时就会因为数据同步问题导致结果不对,显然,输出结果每次都不同,这是无法预知的,下面是输出结果,但是每个线程不会共享for循环中的变量,包括i值。所以如果线程要调用for循环外的变量,要加critical语句,下面有介绍。

//多次输出结果
58504
45203
35716
...
解决方法1:方法一:对操作共享变量的代码段做同步标识
int main()
{
    int n = 100000;
    int sum = 0;
    omp_set_num_threads(4);
    #pragma omp parallel for
    for (int i = 0; i < n; i++)
    {
        #pragma omp critical
        {
            sum++;
        }
    }
    cout << sum << endl;
    return 0;
}

critical制导语句标识的下一行代码,也可以是跟着一个大括号括起来的代码段做了同步处理。
输出结果100000。

猜你喜欢

转载自blog.csdn.net/u010551600/article/details/82627546