随手记录 OpenMP/omp C++ 下 for 并行 多线程加速

前言

一直觉得gpir [高斯过程下的路径规划问题] 这一波,CJ哥的代码学下来的知识真的是太多了,上一篇是有关此的是:【路径规划】OSQP曲线平滑 公式及代码

这一篇主要记录omp库的使用,如何加速C++的整体代码运行的,特别是在有大量for循环下的对比,因为看到gird_map那边多用这个库进行for的并行

python的实现应该是走multiprocess这个库,或者是ray,这一点曾经在这篇博文中写过

GPIR源码地址:https://github.com/jchengai/gpir

从上面摘取示例:

  omp_set_num_threads(4);
  {
#pragma omp parallel for
    // column scan
    for (int x = 0; x < dim[0]; ++x) {
      g[x][0] = is_occupied(x, 0) ? 0 : inf;


      for (int y = 1; y < dim[1]; ++y) {
        g[x][y] = is_occupied(x, y) ? 0 : 1 + g[x][y - 1];
      }


      for (int y = dim[1] - 2; y >= 0; --y) {
        if (g[x][y + 1] < g[x][y]) g[x][y] = 1 + g[x][y + 1];
      }
    }
  }

相关深入可参考链接:https://www.cnblogs.com/mtcnn/p/9411892.html

官方OpenMP地址:https://www.openmp.org/spec-html/5.0/openmp.html

测试

ubuntu下需要安装一下

sudo apt install -y libomp-dev 

CMakeLists.txt配置

cmake_minimum_required(VERSION 3.13.0)
project(common CXX)

set(CMAKE_CXX_STANDARD 14)

find_package(OpenMP REQUIRED)
if (OPENMP_FOUND)
	message("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()

add_executable(omp_example src/omp_test/omp_example.cpp)

普通测试

cpp文件:来源于参考链接处

#include <iostream>
#include "omp.h"

using namespace std;

void test()
{
	for (int i = 0; i < 80000; i++)
	{
	}
}

int main(int argc, char const* argv[]) 
{
	float startTime = omp_get_wtime();

	//指定2个线程
#pragma omp parallel for num_threads(2)
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
	float endTime = omp_get_wtime();
	printf("指定 2 个线程,执行时间: %f\n", endTime - startTime);
	startTime = endTime;

	//指定4个线程
#pragma omp parallel for num_threads(4)
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
	endTime = omp_get_wtime();
	printf("指定 4 个线程,执行时间: %f\n", endTime - startTime);
	startTime = endTime;

	//指定8个线程
#pragma omp parallel for num_threads(8)
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
	endTime = omp_get_wtime();
	printf("指定 8 个线程,执行时间: %f\n", endTime - startTime);
	startTime = endTime;

	//指定12个线程
#pragma omp parallel for num_threads(12)
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
	endTime = omp_get_wtime();
	printf("指定 12 个线程,执行时间: %f\n", endTime - startTime);
	startTime = endTime;

	//不使用OpenMP
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
	endTime = omp_get_wtime();
	printf("不使用OpenMP多线程,执行时间: %f\n", endTime - startTime);
	startTime = endTime;
	return 0;
}

编译测试截图:【注意我测试的主机没有12个线程所以emm就8个】

当时做ray的时候,看到文档中曾说过 如果任务分给每个线程的时间和线程执行的时间差不多,可能越多线程反而速度也会慢下来,这时候主要瓶颈就在分配上了

所以在使用时 只需要前面加上库名,和每个for下指定线程数

#include "omp.h"

  omp_set_num_threads(4);
  {
#pragma omp parallel for
	for (int i = 0; i < 80000; i++)
	{
		test();
	}
  }
          
// ============= OR ==========
#pragma omp parallel for num_threads(4)
	for (int i = 0; i < 80000; i++)
	{
		test();
	}

操作vector

其实和上面差不多,不过想来正好补充一下,顺便说一下,因为ax曾经做一下并行计算的东西,他说如果这个线程要用上一个线程的结果的话,在一些计算量大的情况下会造成堵塞。所以设置for的时候一定要检查一下,比如上面所说的grid map的并行操作的for就是专门设计了for循环以便能达到并行的效果的。更多可见此链接:【基础计算】ESDF栅格距离图计算并行加速版

#include <iostream>
#include "omp.h"
#include <vector>
using namespace std;

void test()
{
	for (int i = 0; i < 16000000; i++)
	{
	}
}

int main(int argc, char const* argv[]) 
{
	float startTime = omp_get_wtime();
	int num=0;
	vector<int> array_num;
	int numP=2;
	omp_set_num_threads(numP);
	{
#pragma omp parallel for
	for (int i = 0; i < 800; i++)
	{
		test();
		num++;
		array_num.push_back(num);
	}
	float endTime = omp_get_wtime();
	printf("指定 %d 个线程,执行时间: %f\n", numP, endTime - startTime);
	}

相关问题补充

pragma omp parallel forpragma omp parallel区别

问题来源:https://stackoverflow.com/questions/38080818/pragma-omp-parallel-for-vs-pragma-omp-parallel

解答如下,从原链接中英文参考而来

#pragma omp parallel
for(int i=0; i<N; i++) {
   ...
}

这样做,是创建了并行块,for会被运行设置线程的个数次;所以 如下图所示运行,线程数设为4,N=4,那么会输出16次,也就是说这个for被运行了4次

---
#pragma omp parallel for
for(int i=0; i<N; i++) {
   ...
}

这样做则是这个for被拆分成线程数,然后并行运行,所以只输出了一个for的文字,具体可见上一部分的时间对比

posted @ 2022-05-20 19:09  Kin_Zhang  阅读(563)  评论(0编辑  收藏  举报