第四次实验——直方图

来源:互联网 发布:湖广填四川知乎 编辑:程序博客网 时间:2024/05/24 07:07

第四次实验——直方图

实验题目

这次实验课的作业的题目是
给出一个有1000万个小数(0<=x<10)的文本,内容及格式如下:

......8.32392.74152.74581.89069.36191.19347.36772.12568.28183.08022.179......

编写程序将文本读入内存,然后统计数据的分布,并记录统计所花费的时间(从读完文本开始计算)。输出格式为:

0<=x<1:n0条
1<=x<2:n1条
2<=x<3:n2条
3<=x<4:n3条
4<=x<5:n4条
5<=x<6:n5条
6<=x<7:n6条
7<=x<8:n7条
8<=x<9:n8条
9<=x<10:n9条

然后再将程序改造成并行程序。


这次实验我用的编程语言是C++,因为用OpenMP将程序由串行改造成并行很简单方便。虽然最开始学习编程的时候学的是C语言,但是用得少了也确实不太熟练。
其实,主要是为了体验一下OpenMP!!

读文本

这次实验其实并没有很困难的地方,多的好像是开始就被读文本这一步难住了,难点在于怎样去存储这些数据。
怎么做呢?我的想法是用文件输入流ifstream的getline()逐行读入。而从文本读入的是字符流,所以还包括一个步骤是将数据从字符串转换成浮点型。最后用一个vector将数据存起来。

代码:

vector<double> data;//数据容器ifstream file("data.txt");//输入流char buffer[10];//缓冲区while(!file.eof()){    file.getline(buffer, 10);//读取一行(最多10个字符)到缓冲区    double num = atof(buffer); //char[]转double    data.insert(data.end(), num);}

其中
vector要包含头文件”vector”
ifstream要包含头文件”fstream”

记录时间

#include <time.h>int t1 = clock(); //记录运行时间/* * 在这里做统计 */int t2 = clock();int time = t2 - t1; //统计数据分布所话费的时间

统计分布

这个很简单,不多解释

//初始化直方图int histogram[10];for(int i = 0; i < 10; i++){    histogram[i] = 0;}for(unsigned i = 0; i < data.size(); i++){    histogram[(int)data[i]]++;}

输出部分就不写了。

改成并行

既然是用OpenMp,那么只需要在for循环前面加上一行

#pragma omp parallel forfor(unsigned i = 0; i < data.size(); i++){    histogram[(int)data[i]]++;}

分析结果

串行的运行结果:

0 <= x < 1: 1000593条1 <= x < 2: 998788条2 <= x < 3: 998657条3 <= x < 4: 998940条4 <= x < 5: 1001225条5 <= x < 6: 1001866条6 <= x < 7: 1000803条7 <= x < 8: 999321条8 <= x < 9: 1000220条9 <= x < 10: 999587条686ms

启用OpenMP的运行结果:

0 <= x < 1: 932024条1 <= x < 2: 929866条2 <= x < 3: 929916条3 <= x < 4: 929729条4 <= x < 5: 931948条5 <= x < 6: 932499条6 <= x < 7: 926111条7 <= x < 8: 930997条8 <= x < 9: 930107条9 <= x < 10: 930549条312ms

由上面的对比,可以发现改成并行计算的结果是错误的。
这是启用了OpenMP之后,多线程共享了变量histogram[],如果没有对变量做互斥访问的控制,这样的问题就出现了,不过计算花费的时间是明显减少了。

OpenMP还可以加入互斥代码块:

#pragma omp critical{    /*     * 这段代码是互斥的     */}

即代码改成了

#pragma omp parallel forfor(unsigned i = 0; i < data.size(); i++){    #pragma omp critical    {        histogram[(int)data[i]]++;    }}

这样以后,运行的结果变成了

0 <= x < 1: 1000594条1 <= x < 2: 998788条2 <= x < 3: 998657条3 <= x < 4: 998940条4 <= x < 5: 1001225条5 <= x < 6: 1001866条6 <= x < 7: 1000803条7 <= x < 8: 999321条8 <= x < 9: 1000220条9 <= x < 10: 999587条39044 ms

可以看到时间长了好多好多好多好多好多。

0 0
原创粉丝点击