第四次实验——直方图
实验题目
这次实验课的作业的题目是
给出一个有1000万个小数(0<=x<10)的文本,内容及格式如下:
......
8.3239
2.7415
2.7458
1.8906
9.3619
1.1934
7.3677
2.1256
8.2818
3.0802
2.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 for
for(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 for
for(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
可以看到时间长了好多好多好多好多好多。