【问题标题】:Why does my code run slower with multiple threads than with a single thread when it is compiled for profiling (-pg)?为什么我的代码在编译用于分析 (-pg) 时,多线程运行比单线程运行慢?
【发布时间】:2010-05-21 06:33:28
【问题描述】:

我正在编写光线追踪器。

最近,我在程序中添加了线程,以利用 i5 四核上的额外内核。

奇怪的是,应用程序的调试版本现在运行速度较慢,但​​优化后的构建运行速度比我添加线程之前更快。

我将“-g -pg”标志传递给 gcc 以进行调试构建,并将“-O3”标志传递给优化构建。

主机系统:Ubuntu Linux 10.4 AMD64。

我知道调试符号会给程序增加很大的开销,但相对性能一直保持不变。 IE。更快的算法在调试和优化构建中总是运行得更快。

知道为什么我会看到这种行为吗?

调试版本使用“-g3 -pg”编译。带有“-O3”的优化版本。

Optimized no threading:        0m4.864s
Optimized threading:           0m2.075s

Debug no threading:            0m30.351s
Debug threading:               0m39.860s
Debug threading after "strip": 0m39.767s

Debug no threading (no-pg):    0m10.428s
Debug threading (no-pg):       0m4.045s

这让我相信“-g3”不应归咎于奇怪的性能增量,而是“-pg”开关。 “-pg”选项很可能添加了某种锁定机制来衡量线程性能。

由于“-pg”在线程应用程序上无论如何都被破坏了,我将删除它。

【问题讨论】:

  • strip 您的调试版本,测量剥离的调试版本的性能并将此信息添加到您的问题中。
  • -pg 没有添加调试符号,所以你的问题是有缺陷的。 “为什么调试符号会对性能产生不利影响”的答案是“它们不会”。

标签: linux performance multithreading gcc gprof


【解决方案1】:

没有-pg 标志你会得到什么?那不是调试符号(不影响代码生成),那是用于分析(确实如此)。

很有可能在多线程进程中进行分析需要额外的锁定,这会减慢多线程版本的速度,甚至会使其比非多线程版本慢。

【讨论】:

  • -pg 启用 gprof 分析,就像答案所暗示的那样,会减慢代码速度。
【解决方案2】:

您在这里谈论的是两件不同的事情。调试符号和编译器优化。如果您使用编译器必须提供的最强优化设置,那么这样做的后果是丢失了对调试有用的符号。

您的应用程序运行速度不是因为调试符号而变慢,它运行速度变慢是因为编译器完成的优化较少。

除了占用更多磁盘空间之外,调试符号并不是“开销”。以最大优化 (-O3) 编译的代码不应添加调试符号。这是您在不需要所述符号时设置的标志。

如果您需要调试符号,则以失去编译器优化为代价获得它们。然而,再一次,这不是“开销”,它只是没有编译器优化。

【讨论】:

  • 我知道调试符号和优化之间有什么区别。我看到的问题是两种算法的相对性能在优化版本和调试版本中是不同的。
  • @fluffels - 我不明白为什么这是出乎意料的?
  • 我期待调试符号/优化对两种算法产生或多或少相同的影响,保持它们之间的相对性能。回想起来,这似乎很幼稚。但是由于第二种算法是线程化的并且问题是高度并行的,我仍然希望相对性能保持不变。我只想知道为什么我错了;)
  • “以最大优化 (-O3) 编译的代码不应添加调试符号。当您不需要所述符号时,您可以设置该标志。” 什么?不。对于 GCC,调试符号(由-g 控制)和优化级别(例如-O3)是正交的,你可以使用-g -O3 而不会“失去编译器优化的代价”,你只会变得不那么有用调试信息,因为高度优化的代码与原始源代码不太相似。
【解决方案3】:

配置文件代码中插入检测调用的功能是否足以伤害您?
如果您在汇编语言级别单步执行,您会很快发现。

【讨论】:

    【解决方案4】:

    多线程代码执行时间并不总是如 gprof 预期的那样测量。 除了 gprof 之外,您还应该使用其他计时器对代码进行计时以查看差异。

    我的示例:在 2NUMA 节点的 INTEL 沙桥(8 核 + 8 核)上运行 LULESH CORAL 基准测试,大小为 -s 50 和 20 次迭代 -i,使用 gcc 6.3.0,-O3 编译,我有:

    运行 1 个线程:~3,7 没有 -pg 和 ~3,8 有它,但根据 gprof 分析,代码只运行了 3 个, 5.

    运行 16 个线程:~0,6 没有 -pg 和 ~0,8,但根据 gprof 分析,代码已经运行了 ~4, 5 ...

    粗体中的时间已在 gettimeofday 中测量,在并行区域之外(主函数的开始和结束)。

    因此,也许如果您以相同的方式测量您的应用程序时间,您会看到使用和不使用 -pg 时相同的 speeduo。只是 gprof 度量是并行错误的。无论哪种方式,在 LULESH openmp 版本中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-15
      • 1970-01-01
      • 2022-11-11
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多