以上代码中,#pragma omp parallel for

这一行的作用即是调用openmp的功能,根据检测到的CPU核心数目,将for (i = 0; i < 1000000000; i++)这个循环执行过程平均分配给每一个CPU核心

去掉#pragma omp parallel for这行,则和普通的串行代码效果一致。

注意,要使用openmp功能,在编译的时候需要加上-fopenmp编译参数。

以下是两种编译搭配两种代码出现的4种结果,可以很直观地看到效果:

1、代码里含有#pragma omp parallel for,编译参数有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test -fopenmp

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 50202611.00 clock tick.

2、代码里含有#pragma omp parallel for,编译参数没有-fopenmp

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4068178.00 clock tick.

3、代码里没有#pragma omp parallel for,编译参数有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test -fopenmp

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4090744.00 clock tick.

4、代码里没有#pragma omp parallel for,编译参数没有-fopenmp

Endys-MacBook-Pro:Desktop endy$ vi test.c

Endys-MacBook-Pro:Desktop endy$ gcc-6 test.c -o test

Endys-MacBook-Pro:Desktop endy$ ./test

Program costs 4170093.00 clock tick.

可以看出,只有在情况1下,openmp生效,其他3种情况下,均为单核运行,2、3、4结果较为接近,而1的运行结果大约相差25%。

值得注意的是,使用多核心的case 1竟然比单核的其他3种case慢了25%,原因是在这种单一的循环运算中,并行分配CPU任务的指令比直接执行下一个循环指令的效率更低。所以并不是用并行运算就一定能够提高运算效率的,要根据实际情况来判断。

#include<stdio.h>
#include<time.h>
#include<omp.h>
int main()
{
long long i;
clock_t t1,t2;
double t3,sum=;
t1=clock(); #pragma omp parallel for
{
//#pragma omp
for(int j=;j<;j++)
{
for(i=;i<=;i++)
{
sum=sum+i/;
}
printf("%d\n",j);
}
} t2=clock();
t3 =t2-t1;
t3 = t3/CLOCKS_PER_SEC;
printf("%f s\n",t3);
return ;
}

这个代码能体现openmp 的功能

1.另外注意哪些可以并行

2.哪些不能并行

3.简单的不需要并行,可能会比串行花费更多时间

在linux g++下的命令如下:

g++ program.cpp -o program -fopenmp

或者:g++ -fopenmp grogram.cpp -o program

./program

继续上面的例子来说:

上述代码中求出的sum有误。因为sum是共享的,那么多个线程对sum的操作会引发数据竞争。

解决办法:reduction

#include<stdio.h>
#include<time.h>
#include<omp.h>
#include<vector>
using namespace std;
int main()
{
long long i;
clock_t t1,t2;
double t3,sum1=1,sum2=;
t1=clock();
vector<int>ve;
printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads());
#pragma omp parallel for reduction(+: sum1,sum2)
for(int j=; j<; j++)
{
sum1+=;
sum2+=;
printf("%d %f %f\n",j,sum1,sum2);
} t2=clock();
t3 =t2-t1;
t3 = t3/CLOCKS_PER_SEC;
printf("%f s\t %f\t %f\n",t3,sum1,sum2);
return ;
}

reduction声明可以看作:

1. 保证了对sum的原则操作

2. 多个线程的执行结果通过reduction中声明的操作符进行计算,以加法操作符为例:

假设sum的初始值为10(如上述代码中),reduction(+: sum)声明的并行区域中每个线程的sum初始值为0(规定),

并行处理结束之后,会将sum的初始化值10以及每个线程所计算的sum值相加。

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

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

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

+                   整数、浮点               0

-                    整数、浮点               0

*                   整数、浮点               1

&                   整数                        所有位均为1

|                    整数                        0
^                   整数                        0

&&                 整数                        1

||                   整数                        0

vector 并行插入问题:

std::vector<int> vec;
#pragma omp parallel
{
std::vector<int> vec_private;
#pragma omp for nowait //fill vec_private in parallel
for(int i=; i<; i++) {
vec_private.push_back(i);
}
#pragma omp critical
vec.insert(vec.end(), vec_private.begin(), vec_private.end());
}
#pragma omp critical保证执行完子线程后,在执行主线程

C++ openmp并行程序在多核linux上如何最大化使用cpu的更多相关文章

  1. 如何利用mono把.net windows service程序迁移到linux上

    How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上 ...

  2. .Net程序跑在Linux上

    .Net越来越拥抱开源了,今天就试了如何让.Net程序跑在Linux上,果然再无人可以阻挡.Net的脚步了. Linux Disibutaion:Open Logic 7.2 1.Install .N ...

  3. Linux上如何查看物理CPU个数,核数,线程数

    首先,看看什么是超线程概念 超线程技术就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的 ...

  4. OpenMP并行编程

    什么是OpenMP?“OpenMP (Open Multi-Processing) is an application programming interface (API) that support ...

  5. 在 Oracle Linux 上使用 DTrace

    作者:Richard Friedman 简要介绍适用于 Oracle Linux 的 DTrace 探测器和提供程序,以及与 Oracle Solaris 中 DTrace 探测器和提供程序的区别.还 ...

  6. 如何将.Net Core应用程序部署在Linux操作系统上运行

    .Net Core简介 跨平台: 可以在 Windows.macOS 和 Linux 操作系统上运行. 跨体系结构保持一致: 在多个体系结构(包括 x64.x86 和 ARM)上以相同的行为运行代码. ...

  7. 不装mono,你的.NET程序照样可以在Linux上运行!

    让.NET应用程序在linux上运行,目前通用的做法就是在Linux上安装mono,然后通过”mono your.exe“命令运行这个程序. 这种运行.net程序的办法有两个弱点,一个是需要客户机安装 ...

  8. Linux上如何执行java程序

    想要在Ubuntu上运行java程序,可以将java程序编译成功后打包,然后在Ubuntu上用命令执行jar文件 具体操作如下: 1.Windows上使用eclipse编译java工程,编译完成后导出 ...

  9. 使用VS GDB扩充套件在VS上远端侦错Linux上的C/C++程序

    在 Linux 上开发 C/C++ 程序,或许你会直接(本机或远端)登入 Linux,打开编辑器写完代码后,就用 gcc/g++ 来编译,遇到要除错(debug)的时候,则会选择使用 gdb 来进行除 ...

随机推荐

  1. mac tomcat安装

    https://blog.csdn.net/qq_35106903/article/details/78860121

  2. if、else、else if后的条件执行体

    if.else.else if后的条件执行体有两种情况:一种是用大括号“{ }”括起来的代码块,这个代码块被称作条件执行体:另一种是以分号“:”作为结束符的单行语句或空语句(仅有一个分号),这个单行语 ...

  3. spring boot application.properties详解

    附上最新文档地址:https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-propertie ...

  4. JAVA的第二次作业

    1.编写“人”类及其测试类.1.1 “人”类: 类名:Person 属性:姓名.性别.年龄.身份证号码 方法:在控制台输出各个信息1.2 测试类 类名:TestPerson 方法:main ...

  5. 最大化系统并发连接数.Windows.reg

    最大化系统并发连接数.Windows.reg Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentContro ...

  6. Hive学习笔记记录

    典型数据来源: 文件管理服务: FTP文件服务:采用c/s模式,用户可以通过不同的客户端实现文件的上传与下载. NFS文件服务:借助于TCP/IP协议实现网络文件共享 Samba文件服务:是一种在局域 ...

  7. 字符IO流

    输入 FileReader的用法: 1. 找到目标文件 2. 建立数据的输入通道 3. 读取数据 4. 关闭资源 具体实例:从硬盘中读取文件 输出 FileWriter的使用步骤: 1. 找到目标文件 ...

  8. ThingJS平台制作第一人称视角下的巡更效果

    今天想要做一个类似巡更的过程,就像是在学校保安巡更,小区保安巡更一样.巡更需要用到相应的场景,比如说:园区.学校.超市以及工厂等等,然后需要规划好路线也就是巡更的路线,并且视角要跟随路线来变换,从而达 ...

  9. VMware要不要装在固态SSD上,虚拟机系统文件要不要放固态SSD上,虚拟机伤不伤固态SSD

    先说结论:VMware建议装在固态上运行快,系统文件最好放在机械硬盘上(有钱除外),虚拟机会伤固态. 今天在学淘淘商城中的搜索项目,克隆了一个虚拟机,这个虚拟机开机贼慢,令人无法忍受,我觉得我再也受不 ...

  10. 关于d3.js 将一个element 拖拽到另一个element的响应事件

    rt 正在做机柜可视化, 一个需求是能拖拽左侧列表的设备名称, 拖到右侧42U机柜中,并将设备图片放置在对应机柜位置上. 开始的时候一切都很顺利,点击左侧设备名称,添加一个g容器,将设备名称作为tex ...