openMP并行运算调用方法来提高运算速度C++

 1 #include <iostream>
   #include <omp.h>
 2 int main(){
 3     int sum = 0;
 4     int a[10] = {1,2,3,4,5,6,7,8,9,10};
 5 #pragma omp parallel for reduction(+:sum)
 6     for (int i=0;i<10;i++)
 7         sum = sum + a[i];
 8     std::cout<<"sum: "<<sum<<std::endl;
 9     return 0;
10 }

#progma omp parallel for表示并行执行for循环

sum变量坐归一化处理(加法+),否则可能出现sum变量操作的时候冲突,导致结果不一致;

其他可以归一化符号:

reduction (operator: var1, val2, ...)

其中operator以及约定变量的初始值如下:

运算符            数据类型                  默认初始值

+                   整数、浮点               0

-                    整数、浮点               0

*                   整数、浮点               1

&                   整数                        所有位均为1

|                    整数                        0
^                   整数                        0

&&                 整数                        1

||                   整数                        0

并行取最大值

 1 #include <iostream>
 2 int main(){
 3     int max = 0;
 4     int a[10] = {11,2,33,49,113,20,321,250,689,16};
 5 #pragma omp parallel for
 6     for (int i=0;i<10;i++)
 7     {
 8         int temp = a[i];
 9 #pragma omp critical
10         {
11             if (temp > max)
12                 max = temp;
13         }
14     }
15     std::cout<<"max: "<<max<<std::endl;
16     return 0;
17 }

#pragma omp critical 申明临界区 避免冲突情况,但也会导致等待的情况,并行效率可能降低。

并行执行的另外一种方法SECTION

 1 #pragma omp parallel sections
 2 {
 3     #pragma omp section
 4     {
 5         function1();
 6     }
 7   #pragma omp section
 8     {
 9         function2();
10     }
11 }

对于ROS编译还需要在CMakelists中增加

find_package(OpenMP)
if (OPENMP_FOUND)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()

定义调度策略

#pragma omp parallel for schedule(static, 2) //static调度策略,for循环每两次迭代分成一个任务

调度策略     功能                                                                                                           适用情况

static         循环变量区域分为n等份,每个线程评分n份任务                                                 各个cpu的性能差别不大   

dynamic    循环变量区域分为n等份,某个线程执行完1份之后执行其他需要执行的那一份任务     cpu之间运行能力差异较大

guided      循环变量区域由大到小分为不等的n份,运行方法类似于dynamic                           由于任务份数比dynamic,所以可以减少调度开销

runtime     在运行时来适用上述三种调度策略中的一种,默认是使用static

同步机制

single,用在一段只被单个线程执行的代码段之前,表示后面的代码段将被单线程执行。

barrier,用于并行区内代码的线程同步,所有线程执行到barrier时要停止,直到所有线程都执行到barrier时才继续往下执行。

master, 通过#pragma omp mater来声明对应的并行程序块只由主线程完成。

nowait用来取消栅障,其用法如下:

#pragma omp for nowait //不能用#pragma omp parallel for nowait

#pragma omp single nowait

#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件

int main()
{
#pragma omp parallel
    {
#pragma omp for nowait
        for (int i = 0; i < 1000; ++i) 
        {
            std::cout << i << "+" << std::endl;
        }
#pragma omp for
        for (int j = 0; j < 10; ++j) 
        {
            std::cout << j << "-" << std::endl;
        }
    }
    
    return 0;
}

第一个for循环的两个线程中的一个执行完之后,继续往下执行,因此同时打印出了第一个循环的+和第一个循环的-。

#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件

int main()
{
#pragma omp parallel
    {
#pragma omp master
        {
            for (int j = 0; j < 10; ++j) 
            {
                std::cout << j << "-" << std::endl;
            }
        }

        std::cout << "This will printed twice." << std::endl;
    }

    return 0;
}

经过比较,单层for循环加大量重复时有效,其他无效,甚至更慢!!!

参考来源:

https://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html

https://blog.csdn.net/donhao/article/details/5652552

https://blog.csdn.net/donhao/article/details/5657371

https://blog.csdn.net/donhao/article/details/5657428

https://blog.csdn.net/SHU15121856/article/details/79350474

https://blog.csdn.net/weixinhum/article/details/97808767

https://blog.csdn.net/donhao/article/details/5656390

https://blog.csdn.net/donhao/article/details/5657717

猜你喜欢

转载自blog.csdn.net/li4692625/article/details/109377402