首页 > 解决方案 > 线程成功退出后,什么会延迟 pthread_join()?

问题描述

我的主线程创建了 8 个工作线程(在具有 4 核、8 线程 CPU 的机器上),然后使用 pthread_join() 等待它们完成。线程全部成功退出,pthread_join() 成功完成。但是,我记录了线程退出的时间以及 pthread_join() 为最后一个线程完成的时间;线程基本上同时退出(不足为奇——它们正在为要完成的工作队列提供服务),并且 pthread_join() 有时需要很长时间才能完成——我已经看到最后一次超过 15分钟的时间工作线程已退出!

更多信息:工作线程都设置在允许的最高循环调度优先级(SCHED_RR);我尝试将主线程(在 pthread_join()s 上等待)设置为相同的内容,并尝试将其设置为最高的 SCHED_FIFO 优先级(到目前为止,我只看到它需要 27 秒才能完成;更多需要测试)。我的测试非常占用 CPU 和内存,大约需要 90 到 100 分钟才能完成;在此期间,它通常以接近 100% 的容量使用所有 8 个线程,并且很快达到使用 256 GB RAM 的大约 90% 的位置。这是在运行级别 3 的 Linux (Fedora) 操作系统上运行的(因此没有图形或窗口管理器——本质上只是一个终端——因为在通常的运行级别 5 下,使用这么多内存的进程会被系统杀死)。

一个较早的版本需要将近 4 个小时才能完成(我已经做了一些性能改进......)并且我没有费心显式设置主线程的优先级曾经花费了一个多小时 20 分钟的 pthread_join( ) 去完成。我提到它是因为我真的不认为主线程优先级应该是一个很大的问题——机器上基本上没有其他事情发生,甚至网络上也没有。

正如我所提到的,所有线程都以 EXIT_SUCCESS 完成。在轻量级测试中,处理在几秒钟内结束,我看不到这样的延迟。所以我怀疑这是一个调度程序问题。我对调度程序知之甚少,但非正式的印象是,这个线程已经在 pthread_join() 上等待了一个多小时;也许调度程序最终会将其拖入“不太可能需要任何处理时间”任务的队列,并且很少检查它。

好的,最终它完成了。但最终,为了完成我的工作,我必须运行大约 1000 次,其中一些可能需要比我一直在测试的案例需要的 90 分钟左右更长的时间。所以我不得不担心这些情况下的 pthread_join() 可能会延迟更长的时间,并且在 1000 次迭代中,这些延迟会实时叠加......

在此先感谢您的任何建议。

针对 Nate 的出色问题和建议:

  1. top当它处于这种状态时,我曾经监视过进程;我所能报告的是,它使用的 CPU 最少(可能偶尔为 2%,而通常top报告 8 个线程完全耗尽的 700 - 800%,以锁定资源的一些争用为模)。我知道top有各种我没有调查过的选项,并将研究如何运行它以显示有关主线程状态的信息。(我明白了:我可以使用 -H 选项,然后查看 S 列……就可以了。)这绝对不是所有内存都被换出的问题——我的代码非常小心地保持在限制以下物理内存,并执行一些自己的磁盘 I/O 来保存和恢复无法放入内存的信息。因此,任何时候都几乎没有使用虚拟内存。

  2. 我也不喜欢我关于调度程序的理论......这是迄今为止我能想到的最好的......

  3. 至于我如何确定事情何时发生:现有代码确实:

        time_t now;
    
        time(&now);
        printf("Thread exiting, %s", ctime(&now));
    
        pthread_exit(EXIT_SUCCESS);
    

然后主线程执行:

 for (int i = 0; i < WORKER_THREADS; i++)
    {
     pthread_join(threads[i], NULL);
    }

 time(&now);
 printf("Last worker thread has exited, %s", ctime(&now));

我喜欢每次 pthread_join() 返回时打印一些东西的想法,看看我们是在等待第一个线程完成,最后一个线程完成,还是在中间,并且会做出改变。

自从我最初发帖以来,我想到了其他一些可能相关的事实:我正在使用 GMP(GNU 多精度算术)库,我真的无法想象这很重要;而且我还使用第 3 方(开源)库来创建“规范图”,并且该库为了在多线程环境中使用,确实使用了一些thread_local存储空间。我将不得不深入研究细节;尽管如此,清理它似乎并不需要花费任何可观的时间,尤其是在不使用大量 CPU 的情况下。

标签: multithreadingschedulerpthread-jointhread-priority

解决方案


推荐阅读