用于可视化每个线程正在运行的函数的工具

时间:2013-07-01 10:19:15

标签: c++ multithreading

我正在尝试使用多线程C ++应用程序调试性能问题。基本上我的多线程程序(10个线程)比单线程程序慢。

我一直在尝试像valgrind(callgrind),gprof和gdb这样的工具。但到目前为止,我无法弄清楚线程的确切位置以及原因。 gprof和callgrind给了我很多时间花在每个函数上。但是这次包括线程被阻塞的时间吗?是否有任何开源工具可用于调试此问题。

2 个答案:

答案 0 :(得分:1)

即使我没有准备好使用答案,我也会从这里的评论切换,因为还有更多空间可以写和格式化。

你能否澄清“lahks”一词?我发现只有something loosely related on Wiki,但它纯粹的猜测,我不知道你的意思。

你说large number of objects per thread。当你随机抽样/停止时,你是否看过堆栈痕迹?我知道alloc / dealloc是堆栈跟踪中最常见的 leaf ,但* nonleaf * s怎么样?您是否能够看到实际调用alloc / dealloc的内容?这就是抽样方法的要点 - 查看调用的原始内容,并统计估计哪些可能的来源过于频繁地调用它。

由于大量优化或架构不匹配(例如,如果您的应用程序使用任务排队,那么您可能无法观察堆栈跟踪的“更高部分”),那么大多数情况下您只会看到“获取任务” “,”检查任务“,”执行任务“步骤而不是真正的起源),但几乎在每个架构中你都可以适当调整(在任务排队方面 - 只需尝试对任务注册进行抽样!)

另一种方式 - alloc / dealloc膨胀是非常普遍的:它通常与架构和算法有关,或者,与bug有关。然而,这种事情应该很容易观察到,不仅在“优化版本”构建中(在看到堆栈跟踪时存在问题),而且还应该快速显示在“完整调试信息”构建中 - 优化程度较低整个系统将运行速度较慢,但​​您应该能够查看并收集可能来源的所有中间方法。

另一件事:你说“多线程”比“单线程”工作得慢得多。这就产生了一个关于如何你能够在它们之间切换的问题?你有两个单独的实现?或者你只是调整1 workerthread和N workerthreads之间的线程池大小?与“alloc / dealloc”问题交叉 - 可能每个线程都需要每次都执行太多的设置/拆卸?

尝试检查实际上线程(作为一个组,查看线程的生命周期)必须反复准备对比到单线程选项。

例如,单线程以某种方式保存alloc / dealloc并且可能重用某些结构),而N线程可能需要N次相同的结构。如果线程只是重复启动/停止而没有重复使用,那么它们的N *数据可能也不会重复使用,因此N线程可能只是在实际工作之前将准备时间烧掉了。

此外,如果你设法捕获无关的分配方案 - 为什么不进一步追踪:停止后,分配器的跳出并尝试查看什么是涂层。我的意思是,你可以步骤检查写入内存的内容,这可以让你进一步了解实际发生的事情。然而,这可能是一项非常艰巨的任务,特别是因为它必须重复多次。我会把它作为最后的手段。

另一件事是 - 纯粹的猜测 - 你的平台可能在alloc / dealloc中有一些全局锁定来“安全地跟踪”内存管理。这样,如果所有线程都按照自己的意愿管理自己的内存,则线程将在每次内存alloc / dealloc操作时相互等待。更改内存分配方案,或使用不同的内存管理器,或使用堆栈或TLS,或将线程池拆分为单独的进程可能会有所帮助,因为它将无需全局锁定。但是,这只是一个非常遥远的猜测,并没有一个解决方案很容易应用。

我很抱歉这种笼统而模糊的谈话。只提供一些您提供的细节,很难再说些什么了。我故意躲避“工作可视化工具”主题。如果您无法通过样本/停止方法看到正在发生的事情,那么所有可能的“线程可视化”工具很可能没有帮助:它们可能会向您显示与您现在看到的完全相同的内容,因为它们都会分析相同的堆栈跟踪,比手动停止要快一点..

答案 1 :(得分:1)

一种可能性是您在单核CPU上运行多线程代码:)

关于多线程的一个常见误解是你可以获得加速改进只是为了解决这个问题的线程:除非你有一个真正的多核CPU和一个可并行化的问题(即一个可以独立解决的问题),这是错误的子问题)

也许您正在使用不可并行化的问题(例如哈希计算)或使用I / O访问(同样,不可并行化)