基本的 openmp 程序运行速度较慢

basic openmp program runs slower

我正在努力使我的程序 运行 更快,所以我将使用并行计算。在此之前,我尝试了简单的 for 循环,但它 运行 更慢。

打开 mp 之前:

int a[100000] = { 0 };
clock_t begin = clock();

for (int i = 0; i < 100000; i++)
{
    a[i] = i;
}


clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("%lf", elapsed_secs);

打开 mp 后:

int a[100000] = { 0 };
clock_t begin = clock();


#pragma omp parallel for
for (int i = 0; i < 100000; i++)
{
    a[i] = i;
}


clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("%lf", elapsed_secs);

要成功使用您的第一个 OpenMP 并行(多线程)代码示例,您需要从以下两个角度改进您的测试用例:

  1. 使您的示例可测试。为此:

    • 确保您的代码足够复杂,不会让编译器有任何机会 "optimize" 整个循环结束(即防止编译器有点用单个表达式替换整个循环)
    • 您最终可能需要引入函数包装循环并在运行时将参数传递给此函数(通过 argc/argv)以使编译器感到困惑,同时保持代码非常简单
    • 确保使用正确的编译标志(-O2 -fopenmp 用于 GCC,其他一些标志用于其他编译器)
    • 确保你的循环需要足够的时间,并且你使用正确的方法来衡量在循环中花费的时间(其他受访者,包括 Gilles,已经很好地指出了这一点)
  2. 确保你的循环在每次循环迭代中做足够的(理想的计算)工作(即加法、乘法等),以便各种 开销 与在 OpenMP 运行时库内部进行一些幕后工作相关(需要在线程之间进行 "schedule"/plan/distribute 迭代) 不是 "bigger" 有用的工作量 在你的循环迭代中完成。 第二和第三维基百科 OpenMP' parallel for examples 已经足够好,可以满足给定的标准(虽然您的示例不满足)。您正处于仅遵循维基百科示例将帮助您获得一些基本理解的地步。

学习给定的基础知识后,您的下一步将是 (a) 理解 "Data Races" / "Race Conditions" / "Loop Carried Dependencies" 和 (b) 理解 # 之间的 "difference" pragma omp parallel 和#pragma omp for(同样,您需要从书籍或基础 OpenMP 课程中找到简单示例)。

(老实说,所有其他主题,例如 OpenMP 不平衡、动态与静态、内存带宽,只有在您花费至少几天 reading/practicing 来了解更简单的概念后才会有意义)

你说你的代码运行速度比较慢,其实你并不知道。原因是你使用clock()来测量时间,而这个函数统计了当前线程CPU时间,可能还有一个它产生的所有线程。为了评估加速,您需要测量的是 经过的挂钟时间 。为此,OpenMP 为您提供 omp_get_wtime()。尝试在您的代码中使用它,然后您就会真正了解您的代码是否从 OpenMP 中获得任何好处。

现在,让我们明确一点,您的代码只不过是写入内存。因此,您很有可能很快就会使内存带宽饱和。因此,除非您有多个内存控制器,否则在这种情况下您不太可能从添加线程中获益良多。请看看this answer说服自己。

最后,请确保在退出代码之前对数据进行了一些处理,否则,编译器可能只是对其进行了优化,导致代码几乎什么都不做(但速度非常快) .