【问题标题】:openMP for don't improve overal perfomanceopenMP 不会提高整体性能
【发布时间】:2021-10-03 06:46:57
【问题描述】:

我正在使用 c++ dll 来进行一些计算密集型处理——我的 c++ 使用线程——并在我的 c# 应用程序中使用这个 dll。

我使用 MS Visual Studio Profiler 来识别最耗时的代码部分。

并使用 openMP 通过在运行 @2.9GHz 的 Intel i7 8 核处理器之间分配工作负载来提高性能。

例如下面的代码会消耗大量的cpu时间

for (short j = 0; j < 4096; j++)
    histsum[j] = hist_tmp[row][col][0][j] + hist_tmp[row][col][1][j] + hist_tmp[row][col][2][j] + hist_tmp[row][col][3][j];

所以我修改为

#pragma omp parallel for
                for (short j = 0; j < 4096; j++)
                    histsum[j] = hist_tmp[row][col][0][j] + hist_tmp[row][col][1][j] + hist_tmp[row][col][2][j] + hist_tmp[row][col][3][j];

我注意到 8 核是 100% 加载的,但整体性能并没有提高。

可能是什么问题?我该如何克服它?

【问题讨论】:

  • 通常你不会通过使用更多线程来减少cpu时间。这是更多的cpu时间。你想测量挂钟时间而不是 CPU 时间
  • @463035818_is_not_a_number 我知道我并没有减少 CPU 时间,我提到 cpu 已 100% 加载表明 openMP 正在并行化我的代码,并且 cpu 的利用率得到了提高,这是预期的,但是什么是奇怪的是,用挂钟衡量的整体性能下降了,没有提高
  • 我只是在向您指出一些可能是误解的东西。可能只是措辞。你写“消耗CPU的很多时间......所以我将它修改为......”。无论如何,问题中的信息太少,无法知道为什么没有加速。如果您需要代码方面的帮助,您应该包含minimal reproducible example。有关性能的问题通常需要更多信息,您测量的是什么时间?你是怎么测量的?什么编译器?什么编译器标志?等等……
  • 因为工作量很小,开销扼杀了速度的提升。对于现代处理器来说,添加 4 个大小为 4096 的向量是非常小的工作量,不值得并行化..

标签: c# c++ openmp


【解决方案1】:

C++ 和多线程都不会自动提高性能。两者都需要在适当的地方应用才能获得任何好处。

使用多线程有一些开销来委派工作和同步结果。如果每个任务都很小,那么开销将大于任何可能的收益。将四个数字加在一起绝对是很小的,这很有用。您需要将多线程应用于更大的数据块才能发挥作用。

我也不希望通过使用 c++ 编写这样的代码来获得任何巨大的收益。 C++ 编译器通常更擅长优化代码,但对于像这样的简单代码,即使是 c# 编译器也应该做得不错。通过将索引hist_tmp[row][col] 移到循环外,您可能会看到一些小的改进。这个索引可能已经被优化掉了,但它可能值得一试。

然而,这种代码应该受益于 SIMD。一些 c++ 编译器具有自动矢量化选项。为了从 c# 中获得最佳性能,.net core 中有intrinstics

非常重要的一点是使用适合平台的工具衡量性能。在 c# 中,这将是 stopwatch,但建议使用像 benchmark.net 这样的工具,因为它们可以处理诸如编译开销之类的事情。一个好的分析器也非常有用。

我还建议在使用多线程和 C++ 之前寻找任何算法改进、缓存机会或其他不必要或重复的工作。前者通常会对性能产生更大的影响。

【讨论】:

  • 顺便说一句,完全不清楚 OPs 代码添加了什么,它可能是一些带有昂贵 operator+ 的自定义类型。虽然你可能是对的
猜你喜欢
  • 2018-09-25
  • 1970-01-01
  • 2015-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-02
  • 2014-11-25
  • 1970-01-01
相关资源
最近更新 更多