随着线程数增加,OpenMP实现越来越慢

时间:2017-11-08 12:08:04

标签: c++ multithreading

我一直在努力学习使用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.

(我只是注意到串行和并行的图例标签是错误的方法。)

正如您所看到的,使用多个线程会大大增加时间。添加更多线程会增加线程数作为线程数的函数所需的时间。

谁能告诉我发生了什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

对于pm()函数什么都不做,上面的怪异是正确的,编译器感到困惑。

事实证明,rand()函数在使用OpenMP for循环时效果不佳。

添加函数sqrt(i)(我是循环索引)我实现了预期的代码加速。