【问题描述】

编写程序统计一个英文文本文件中每个单词的出现次数(词频统计),并将统计结果按单词字典序输出到屏幕上。

注:在此单词为仅由字母组成的字符序列。包含大写字母的单词应将大写字母转换为小写字母后统计。

【输入形式】

打开当前目录下文件article.txt,从中读取英文单词进行词频统计。

【输出形式】

程序将单词统计结果按单词字典序输出到屏幕上,每行输出一个单词及其出现次数,单词和其出现次数间由一个空格分隔,出现次数后无空格,直接为回车。

【样例输入】

当前目录下文件article.txt内容如下:

Do not take to heart every thing you hear.;

Do not spend all that you have.;

Do not sleep as long as you want;

【样例输出】

all 1

as 2

do 3

every 1

have 1

hear 1

heart 1

long 1

not 3

sleep 1

spend 1

take 1

that 1

thing 1

to 1

want 1

you 3

【样例说明】

输出单词及其出现次数。
数据集下载:wordcount数据集

提取码:k3v2

代码实现:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <omp.h>
using namespace std;int main(int argc, char* argv[]) {int n = atoi(argv[1]);   //线程数ifstream file("input.txt");string word;vector<string> words;map<string, int> wordCount;while (file >> word) {for (int i = 0; i < word.length(); i++) {if (ispunct(word[i])) {word.erase(i--, 1);}}words.push_back(word);}omp_set_num_threads(n);   //设置线程数double starttime = omp_get_wtime();#pragma omp parallel forfor (int i = 0; i < words.size(); i++) {#pragma omp critical{wordCount[words[i]]++;}}double endtime = omp_get_wtime();for (auto it = wordCount.begin(); it != wordCount.end(); it++) {cout << it->first << ": " << it->second << endl;}printf("\n并行时间:%lfs\n", endtime - starttime);return 0;
}

编译:g++ ./filename.cpp -o ./filename -fopenmp

运行:./filename n     n为设置的线程数

运行结果:

一个进程:

4个进程:

可以看到4个进程比

比一个的慢了差不多一倍,这是由于通讯时间比交耗时造成的。

加速比为:1.914/2.751= 0.6957470010905125

由于通讯时间较长反而没达到加速效果。

OpenMP基本概念
OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

在VS中启用OpenMP很简单,很多主流的编译环境都内置了OpenMP。在项目上右键->属性->配置属性->C/C++->语言->OpenMP支持,选择“是”即可。

OpenMP执行模式
OpenMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

一个典型的fork-join执行模型的示意图如下:

OpenMP编程模型以线程为基础,通过编译制导指令制导并行化,有三种编程要素可以实现并行化控制,他们分别是编译制导、API函数集和环境变量。

编译制导
编译制导指令以#pragma omp 开始,后边跟具体的功能指令,格式如:#pragma omp 指令[子句[,子句] …]。常用的功能指令如下:

parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行;
for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性;
parallel for:parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能;
sections:用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出(注意区分sections和section);
parallel sections:parallel和sections两个语句的结合,类似于parallel for;
single:用在并行域内,表示一段只被单个线程执行的代码;
critical:用在一段代码临界区之前,保证每次只有一个OpenMP线程进入;
flush:保证各个OpenMP线程的数据影像的一致性;
barrier:用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才继续往下执行;
atomic:用于指定一个数据操作需要原子性地完成;
master:用于指定一段代码由主线程执行;
threadprivate:用于指定一个或多个变量是线程专用,后面会解释线程专有和私有的区别。
相应的OpenMP子句为:

private:指定一个或多个变量在每个线程中都有它自己的私有副本;
firstprivate:指定一个或多个变量在每个线程都有它自己的私有副本,并且私有变量要在进入并行域或任务分担域时,继承主线程中的同名变量的值作为初值;
lastprivate:是用来指定将线程中的一个或多个私有变量的值在并行处理结束后复制到主线程中的同名变量中,负责拷贝的线程是for或sections任务分担中的最后一个线程; 
reduction:用来指定一个或多个变量是私有的,并且在并行处理结束后这些变量要执行指定的归约运算,并将结果返回给主线程同名变量;
nowait:指出并发线程可以忽略其他制导指令暗含的路障同步;
num_threads:指定并行域内的线程的数目; 
schedule:指定for任务分担中的任务分配调度类型;
shared:指定一个或多个变量为多个线程间的共享变量;
ordered:用来指定for任务分担域内指定代码段需要按照串行循环次序执行;
copyprivate:配合single指令,将指定线程的专有变量广播到并行域内其他线程的同名变量中;
copyin:用来指定一个threadprivate类型的变量需要用主线程同名变量进行初始化;
default:用来指定并行域内的变量的使用方式,缺省是shared。
利用omp_set_num_threads()来设置线程数,

利用#pragma omp parallel sections 声明下面大括号中的语句要并行多线程执行;

利用#pragma omp section 分配线程。

看懂下列helloworld的代码对openmp并行就会有一定了解。

使用omp技术实现wordcount算法相关推荐

  1. 技术图文:排序技术在求解算法题中的应用

    背景 前段时间,在知识星球立了一个Flag,这是总结Leetcode刷题的第五篇图文. 理论部分 C# 中的排序 对集合类的排序,我们通常使用位于 System.Core 程序集,System.Lin ...

  2. DL之DNN优化技术:神经网络算法简介之GD/SGD算法(BP的梯度下降算法)的简介、理解、代码实现、SGD缺点及改进(Momentum/NAG/Ada系列/RMSProp)之详细攻略

    DL之DNN优化技术:神经网络算法简介之GD/SGD算法(BP的梯度下降算法)的简介.理解.代码实现.SGD缺点及改进(Momentum/NAG/Ada系列/RMSProp)之详细攻略 目录 GD算法 ...

  3. DL之DNN优化技术:神经网络算法简介之数据训练优化【mini-batch技术+etc】

    DL之DNN优化技术:神经网络算法简介之数据训练优化[mini-batch技术+etc] 目录 1.mini-batch技术 输出结果 实现代码 1.mini-batch技术 输出结果 实现代码 # ...

  4. DL之DNN优化技术:神经网络算法简介之GD/SGD算法的简介、代码实现、代码调参之详细攻略

    DL之DNN优化技术:神经网络算法简介之GD/SGD算法的简介.代码实现.代码调参之详细攻略 目录 GD算法的简介 GD/SGD算法的代码实现 1.Matlab编程实现 GD算法的改进算法 GD算法中 ...

  5. [译]基于GPU的体渲染高级技术之raycasting算法

    [译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...

  6. 万字综述智能驾驶车载激光雷达关键技术与应用算法

    来源 | 智驾最前沿 编辑 | 焉知智能汽车 随着全球智能驾驶进入产业化与商业化的准备期,车载激光雷达凭借其优异性能已成为不可或缺的环境感知传感器并在硬件技术和应用算法上得到迅猛发展.文章以激光雷达扫 ...

  7. 麻省理工学院的学生们愚弄了谷歌图像识别技术,计算机视觉算法仍然很容易被骗

    文章来源:ATYUN AI平台 人工智能图像识别技术已经取得了一些令人惊叹的进步,但正如一项新的研究表明的那样,这些系统仍然可以被那些愚弄的例子所绊倒. 一群麻省理工学院的学生最近愚弄了谷歌开发的一种 ...

  8. 人脸识别(7)---国内人脸识别技术 十大算法公司排名

    国内人脸识别技术 十大算法公司排名 科技特讯11月18日讯:1.云从科技 背靠"计算机视觉之父",中科院实验室创业团队创立云从科技 云从科技团队成员除了来自中科大的校友外,还来自中 ...

  9. 博弈树搜索技术(Minimax算法,ɑ-β 算法)

    博弈树搜索技术(Minimax算法,ɑ-β 算法) 一. 算法的理解 Minimax算法 概括:算法可以概括为--己方利益最大化,对方利益最小化". 即一方要在可选的选项中选择将其优势最大 ...

最新文章

  1. Oracle触发器修改数据时同步执行插入该条数据
  2. Java中的回调函数学习-深入浅出
  3. SOA面向服务架构打包部署
  4. python opencv image 转 c++ avframe
  5. boost库之tcp server(异步)
  6. Python_位_成员_身份运算符
  7. python中转义字符怎么用_python中的转义字符i
  8. AngularJS快速入门指南14:数据验证
  9. javabean反射改字段内容_java反射机制给实体类相同字段自动赋值实例
  10. 扩展类加载器 Extension ClassLoader
  11. 岗位po是什么意思_面试时,面试官问你有什么优点和缺点?应该如何巧妙的回答?...
  12. Transformer-XL语言模型:超长上下文依赖
  13. oppo手机计算机,OPPO手机助手
  14. Java StringBuilder
  15. 蓝桥杯2019年第十届C/C++省赛C组第六题-旋转
  16. c语言课程设计物业,C语言课程设计报告--物业管理系统.doc
  17. android 改机型玩王者,全机型60帧一键修改
  18. 什么是BASE最终一致性
  19. js 万年历农历转阳历 方法_JavaScript实现公历转农历功能示例
  20. 使用echarts生成漂亮的3D地图

热门文章

  1. Linux 驱动开发 十:《Devicetree Specification》翻译
  2. 微信开发——人脸识别 车牌识别 语言识别
  3. Python根据身份证号计算年龄和退休时间并保存Excel文件
  4. 经典语录大全的一些思考
  5. 4G改变生活,5G改变社会
  6. Linux拷贝U盘文件(命令行)
  7. 【postman】postman中文传参出错
  8. hyperledger v1.0.5 区块链入门
  9. 一种应用更广泛的DLL侧载方法
  10. 机器人的研究,主要经历了哪几代历程?