c++ - OpenMP 没有加速

标签 c++ multithreading parallel-processing openmp

我正在使用 OpenMP 以获得具有近乎线性加速的算法。 不幸的是,我注意到我无法获得所需的加速。

因此,为了理解我的代码中的错误,我编写了另一个代码,一个简单的代码,只是为了仔细检查加速在原则上是否可以在我的硬件上获得。

这是我写的玩具示例:

#include <omp.h>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include "mkl.h"

int main () {
      int number_of_threads = 1;
      int n = 600;
      int m = 50;
      int N = n/number_of_threads;
      int time_limit = 600;
      double total_clock = omp_get_wtime();
      int time_flag = 0;

      #pragma omp parallel num_threads(number_of_threads)
       {
          int thread_id = omp_get_thread_num();
          int iteration_number_local = 0;
          double *C = new double[n]; std::fill(C, C+n, 3.0);
          double *D = new double[n]; std::fill(D, D+n, 3.0);
          double *CD = new double[n]; std::fill(CD, CD+n, 0.0);

          while (time_flag == 0){
                for (int i = 0; i < N; i++)                     
                    for(int z = 0; z < m; z++)
                        for(int x = 0; x < n; x++)
                            for(int c = 0; c < n; c++){
                                CD[c] = C[z]*D[x];
                                C[z] = CD[c] + D[x];
                            }
                iteration_number_local++;
                if ((omp_get_wtime() - total_clock) >= time_limit) 
                    time_flag = 1; 
           }
       #pragma omp critical
       std::cout<<"I am "<<thread_id<<" and I got" <<iteration_number_local<<"iterations."<<std::endl;
       }
    }

我想再次强调,这段代码只是一个尝试查看加速的玩具示例:当并行线程数量增加时(因为 N 减少),第一个 for-cycle 变得更短。

但是,当我从 1 个线程增加到 2-4 个线程时,迭代次数会按预期增加一倍;但是当我使用 8-10-20 个线程时情况并非如此:迭代次数不会随线程数线性增加。

你能帮我解决这个问题吗?代码是否正确?我应该期待接近线性的加速吗?

Results

Running the code above I got the following results.

1 thread: 23 iterations.

20 threads: 397-401 iterations per thread (instead of 420-460).

最佳答案

您的衡量方法有误。特别是对于少量迭代。

1 thread: 3 iterations.

3 次报告的迭代实际上意味着 2 次迭代在不到 120 秒内完成。第三个花了更长的时间。 1次迭代的时间在40~60 s之间。

2 threads: 5 iterations per thread (instead of 6).

4 次迭代在不到 120 秒的时间内完成。 1次迭代的时间在24~30 s之间。

20 threads: 40-44 iterations per thread (instead of 60).

40 次迭代在不到 120 秒的时间内完成。 1次迭代的时间在2.9~3 s之间。

如您所见,您的结果实际上与线性加速并不矛盾。

简单地执行一个外部循环并为其计时会更简单、更准确,您可能会看到近乎完美的线性加速。

您看不到线性加速的一些原因(非详尽)是:

  1. 内存限制性能。在您使用 n = 1000 的玩具示例中并非如此。更一般地说:争用共享资源(主内存、高速缓存、I/O)。
  2. 线程之间的同步(例如关键部分)。在您的玩具示例中并非如此。
  3. 线程之间的负载不平衡。在您的玩具示例中并非如此。
  4. 当所有核心都被利用时,Turbo 模式将使用较低的频率。这可能发生在您的玩具示例中。

从您的玩具示例中,我会说可以通过更好地使用高级抽象来改进您的 OpenMP 方法,例如

更一般的建议对于这种格式来说过于宽泛,需要有关非玩具示例的更多具体信息。

关于c++ - OpenMP 没有加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38630633/

相关文章:

iOS AudioSessionSetActive() 阻塞主线程?

c++ - 同步非常快的线程

php - Apache + PHP 同时运行多个脚本

.net - 并发垃圾回收如何与并行计算一起工作?

c++ - 用C++编译gpsd客户端

c++ - C/C++ 中 offsetof 宏的合法使用

c++ - 处理数组队列

c++ - 如何处理具有 IWebBrowser2 对象的 IHttpSecurity::OnSecurityProblem

c - 此解决方案中的信号量使用是否正确?

c++ - parallel_for 函数导致内存泄漏(有时)