添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
本文介绍了如何在GPIR路径规划问题中利用OpenMP库加速C++代码,通过omp_set_num_threads和#pragma omp parallel for实现并行计算,对比不同线程数对代码执行时间的影响,以及在操作vector时的注意事项。 摘要由CSDN通过智能技术生成

一直觉得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的文字,具体可见上一部分的时间对比

OpenMP缺点: 1:作为高层抽象,OpenMp并不适合需要复杂的线程间同步和互斥的场合; 2:另一个缺点是不能在非共享内存系统(如计算机集群)上使用。在这样的系统上,MPI使用较多。 基本使用: 在visual C++2010中使用OpenMP 1:将 Project 的Properties中C/C++ float renderFrame() { omp_set_num_threads(20); //设置线程的个数 double start = omp_get_wtime();//获取起始时间 #pragma omp parallel for for (int i = parallel for 用于for循环之前,表示下面的for的循环并行执行,但是要求每次循环没有相关性 4.函数常用函数 int omp_get_thread_num(void);//返回当前线程的编号 int omp_get_num_threads(void);//返回当前运行线程的总数 void omp
C++语言并没有对多线程与网络的良好支持,虽然新的C++标准加入了基本的`thread`库,但是对于并发编程的支持仍然很基础,Boost库提供了数个用于实现高并发与网络相关的开发库这让我们在开发跨平台并发网络应用时能够像Java等语言一样高效开发。 thread库为C++增加了多线程处理能力,其主要提供了清晰的,互斥量,线程,条件变量等,可以很容易的实现多线程应用开发,而且该库是可跨平台的,并且支持`POSIX`和`Windows`线程。