OpenMP实验
OpenMP实验
矩阵乘法的OpenMP实现及性能分析
1)运行并测试矩阵相乘程序
测试结果:
并行加速比表格:
线程数 | 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 |
---|---|---|---|---|---|---|---|---|---|
运行时间(预期) | 0.088 | 0.044 | 0.022 | 0.015 | 0.011 | 0.008 | 0.007 | 0.006 | 0.0055 |
运行时间(实际) | 0.088 | 0.046 | 0.026 | 0.023 | 0.028 | 0.042 | 0.045 | 0.046 | 0.05 |
加速比 | 1 | 1.91 | 3.38 | 3.83 | 3.14 | 2.10 | 1.96 | 1.91 | 1.76 |
2)上述的并行加速效果如何?为什么?请尽可能优化上述程序,重做一个并行加速比表格
上述并行的加速效果在线程数达到6时达到最佳,之后则逐渐变差。
推测原因可能是:
- OpenMP的parallel region结束时,线程之间需要同步:即主线程需要等待所有其他线程完成工作之后才能继续。
程序优化:在网络上查找到优化的方法
-
openmp的for循环中不应当包含有rand。这里我们没有使用rand
-
应当先由编译器对程序进行优化。在VS下设置步骤为:首先把解决方案配置由debug调整为release(debug默认不优化),然后点击配置,把优化等级改为优选速度(O2)
再次运行程序:
可以看到程序的运行速度大大加快,已经快了一个数量级。但是可以看到单核的性能甚至比除了4核以外的多核性能都要好,该原因尚不清楚。
- 发现clock计时函数的一些问题。clock()为各个核心计算用时之和(一般约为并行线程个数与omp_get_wtime()乘积)。它的问题在于如果只是简单的线性执行的程序,那么使用clock() 就可以计算出程序的执行时间,但是其实这个时间是CPU的时间。如果你用clock()计算并行程序执行时间,发现它会把所有CPU的执行都叠加起来。因为我们使用的并行程序,因此不应该使用clock(),而应当使用openMp提供的计时函数omp_get_wtime()。
再次运行程序:
发现并没有什么区别,甚至时间更长了。看到有说法说Linux下有区别,VS上两个都一样,遂作罢。
重新计算并行加速比
线程数 | 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 |
---|---|---|---|---|---|---|---|---|---|
运行时间(预期) | 0.005 | 0.0025 | 0.00125 | 0.0008 | 0.0006 | 0.0005 | 0.0004 | 0.0003 | 0.0003 |
运行时间(实际) | 0.005 | 0.009 | 0.006 | 0.005 | 0.006 | 0.008 | 0.006 | 0.007 | 0.006 |
加速比 | 1 | 0.56 | 0.83 | 1 | 0.83 | 0.625 | 0.83 | 0.71 | 0.83 |
3)请自行编写一个OpenMP程序,用多线程并行计算两个n阶方阵相乘(一次),n从200以200步速增加到1000,记录下不同n时不同线程数的程序运行时间,分析并行效果。
定义一个结构体Matrix代表矩阵,因此就可分别设定不同规模的矩阵相乘。至于并行计算部分代码则使用实验指导书的。下面是自定义结构体相关函数:
struct Matrix//矩阵结构体
{
int len;
int** p;
Matrix(int len);
Matrix();
void setRand();
void setLen(int len);
};
void comput(Matrix& A, Matrix& B, Matrix& C) { //两个矩阵相乘
int r, c;
for (r = 0; r < C.len; r++)
for (c = 0; c < C.len; c++) {
for (int i = 0; i < C.len; i++)
C.p[r][c] += A.p[r][i] * B.p[i][c];
}
}
运行结果如下图(采用编译器优化):
详细列出不同矩阵规模不同线程数下的运行时间,可以看出各个线程数下,随着矩阵规模的增大,运行时间逐渐变长:
做出其并行加速比表格(采用编译器优化):
线程数 | 1 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 |
---|---|---|---|---|---|---|---|---|---|
运行时间(预期) | 2.75 | 1.375 | 0.69 | 0.46 | 0.34 | 0.27 | 0.23 | 0.20 | 0.17 |
运行时间(实际) | 2.75 | 2.27 | 1.62 | 1.57 | 1.73 | 1.64 | 1.64 | 1.67 | 1.61 |
加速比 | 1 | 1.21 | 1.70 | 1.75 | 1.59 | 1.68 | 1.68 | 1.65 | 1.71 |
可以看到仍然是在线程数为6时加速比最高,但是当线程数超过12时,运行时间同样较为理想。