我能否强制 C++ 库使用单个线程?

4
我在Linux上使用一个专有的C++库,通过gcc编译,该库使用pthreads(我必须在gcc上使用-lpthread标志)。我有一个包装器,我知道该库正在使用多个线程。 该库动态地使用多个线程 - 当我调用它时,我可以看到20到1个线程。 但是我不想使用taskset。(我有其他进程在运行,我希望系统管理核心)。
有没有一种方法可以强制我的可执行文件使用单个线程? 无论是在编译还是在运行时。谢谢。
编辑: 我可以使用taskset运行可执行文件,然后cat /proc/ /status给出:
状态:R(运行) Tgid:1623 Pid:1623 PPid:31002 TracerPid:0 Uid:500 500 500 500 Gid:100 100 100 100 Utrace:0 FDSize:256 Groups:100 VmPeak:346528 kB VmSize:345956 kB VmLck:0 kB VmHWM:199816 kB VmRSS:188388 kB VmData:192120 kB VmStk:128 kB VmExe:656 kB VmLib:12444 kB VmPTE:432 kB VmSwap:0 kB Threads:1 SigQ:2/62004 SigPnd:0000000000000000 ShdPnd:0000000000000000 SigBlk:0000000000000000 SigIgn:0000000000000004 SigCgt:0000000180000000 CapInh:0000000000000000 CapPrm:0000000000000000 CapEff:0000000000000000 CapBnd:ffffffffffffffff Cpus_allowed:02 Cpus_allowed_list:1 Mems_allowed:00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001 Mems_allowed_list:0 voluntary_ctxt_switches:3460 nonvoluntary_ctxt_switches:24907
因此,显然它可以运行单个线程。

2
你知道如果只允许一个线程,这个库可能/很可能不再起作用了吗?也许你的意思是限制可执行文件的执行到单个核心上? - Simon Kraemer
我需要测试一下可能性,我知道它可能行不通。 可执行文件使用了库,所以我不明白你所说的“限制可执行文件而不是库”的意思。当我运行可执行文件时,它会调用库中的多线程函数。 - mousomer
1
是的,该库依赖于这些线程。假设该库在2个不同的线程中处理2个消息队列。如果现在消除多线程:哪个线程/消息队列被允许运行?另一个呢?该库使用pthread的原因可能是有道理的。 - Simon Kraemer
3
你的问题不是很清楚。如果某个东西使用了多线程,它就不能使用单线程,因为它是这样设计的。如果已经只使用了一个线程,那么问题是什么?也许你把线程和核心搞混了?多线程可以在单个核心上运行。 - ElderBug
1
我投票关闭此问题,因为它似乎是由于误解线程的概念而产生的。 - MSalters
显示剩余2条评论
3个回答

5

如果您不关心线程的生成,只想让程序按顺序执行,您可以在Linux上使用numactl。

这个回答中得知,您可以使用以下方法将程序限制为一次同时执行一个线程:

numactl --physcpubind=+1 /path/to/your/executable

来自 numactl 文档:

--physcpubind=cpus, -C cpus

仅在 cpus 上执行 process。它接受像 /proc/cpuinfo 处理器字段中显示的 cpu 数或相对于当前 cpuset 的 cpu。

该程序仍会生成线程,但受限于在单个 CPU 上执行。这意味着只能同时运行一个线程。


1

如果不知道您想做什么,那只有一个答案:不可能。

你如何限制某个东西不使用多线程?禁用pthread_create()只会使程序无法正常运行。想象一下,库会生成一个线程来异步处理文件。如果禁止pthread_create(),那么文件操作会发生什么?该库现在无法正常工作,因为它无法执行文件操作。您需要完全重新设计该库;将文件IO放在同一个线程上(如果可能的话)可能会导致灾难性后果,因为该线程应该是自由运行的,现在却被一些繁重的IO阻塞了。

这就是一般的想法。无论是否真正需要线程,如果一个库被设计成多线程,您都不能简单地将其变为单线程。但是您可以使用taskset,如您所提到的,或者使用C/C++中的sched_setaffinity()将进程运行在单个核心上。


任务集正常工作。当我使用任务集运行时,该库不会生成多个线程,实际上运行速度快了70%。 我仍然不确定任务集是否完全符合我的要求。 - mousomer
@mousomer 当然,这个库可能设计得很糟糕,但我觉得奇怪的是,在 taskset 之后它会有不同的行为。也许该库正在计算核心数,但我不确定 taskset 是否会影响库读取的数量。您是否检查过该库是否有选项来控制线程? - ElderBug
我检查了一下,它没有线程控制器。 似乎该库有失控的线程影响运行时。 使用taskset,每个数据文件需要600毫秒,但是没有使用taskset则需要2.5秒。问题是,服务器正在运行其他任务。使用taskset会有问题吗?它不会干扰其他进程吗? - mousomer
1
@mousomer 这真的取决于你想要实现什么以及如何实现。如果你在同一个核心上使用了很多 taskset,显然这不是好的选择。关于 lib,如果它的工作是异步处理文件,可能减速只是因为磁盘访问。如果是这种情况,你应该等待一个文件完成后再处理下一个(说实话,lib 应该负责这个)。 - ElderBug

0

我不太了解进程的内部细节。但是为什么不增强你的代码库以限制创建超过1个线程。你可以维护线程计数,并在计数达到1以上时停止在进程中创建线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接