我一直在努力学习使用OpenMP。但是我的代码似乎在串行运行得更快。
实际上使用的线程越多,计算时间就越慢。
为了说明这一点,我进行了一项实验。我正在尝试执行以下操作:
long int C[num], D[num];
for (i=0; i<num; i++) C[i] = i;
for (i=0; i<num; i++){
for (j=0; j<N; j++) {
D[i] = pm(C[i]);
}
}
函数pm只是
int pm(int val) {
val++;
val--;
return val;
}
我并行实现了内部循环,并将运行时间与内循环(N)上的迭代次数和使用的线程数进行了比较。实验代码如下。
#include <stdio.h>
#include <iostream>
#include <time.h>
#include "omp.h"
#include <fstream>
#include <cstdlib>
#include <cmath>
static long num = 1000;
using namespace std;
int pm(int val) {
val++;
val--;
return val;
}
int main() {
int i, j, k, l;
int iter = 8;
int iterT = 4;
long inum[iter];
for (i=0; i<iter; i++) inum[i] = pow(10, i);
double serial[iter][iterT], parallel[iter][iterT];
ofstream outdata;
outdata.open("output.dat");
if (!outdata) {
std::cerr << "Could not open file." << std::endl;
exit(1);
}
"""Experiment Start"""
for (l=1; l<iterT+1; l++) {
for (k=0; k<iter; k++) {
clock_t start = clock();
long int A[num], B[num];
omp_set_num_threads(l);
for (i=0; i<num; i++) A[i] = i;
for (i=0; i<num; i++){
#pragma omp parallel for schedule(static)
for (j=0; j<inum[k]; j++) {
B[i] = pm(A[i]);
}
}
clock_t finish = clock();
parallel[k][l-1] = (double) (finish - start) /\
CLOCKS_PER_SEC * 1000.0;
start = clock();
long int C[num], D[num];
for (i=0; i<num; i++) C[i] = i;
for (i=0; i<num; i++){
for (j=0; j<inum[k]; j++) {
D[i] = pm(C[i]);
}
}
finish = clock();
serial[k][l-1] = (double) (finish - start) /\
CLOCKS_PER_SEC * 1000.0;
}
}
"""Experiment End"""
for (j=0; j<iterT; j++) {
for (i=0; i<iter; i++) {
outdata << inum[i] << " " << j + 1 << " " << serial[i][j]\
<< " " << parallel[i][j]<< std::endl;
}
}
outdata.close();
return 0;
}
下面的链接是每个线程数的log(T)与log(N)的关系图。
A plot of the run times for varying number of threads and magnitude of computational task.
(我只是注意到串行和并行的图例标签是错误的方法。)
正如您所看到的,使用多个线程会大大增加时间。添加更多线程会增加线程数作为线程数的函数所需的时间。
谁能告诉我发生了什么?
谢谢!
答案 0 :(得分:0)
对于pm()函数什么都不做,上面的怪异是正确的,编译器感到困惑。
事实证明,rand()函数在使用OpenMP for循环时效果不佳。
添加函数sqrt(i)(我是循环索引)我实现了预期的代码加速。