C++ 睡眠限制了线程性能

C++ 睡眠限制了线程性能,c++,pthreads,sleep,C++,Pthreads,Sleep,我有一个多线程系统,其中有x个线程同时向网络发送数据包 这一切都可以很好的工作任何花花公子,但是一些线程我想限制他们的速度,以发送数据包在一定的速度 所以我在我的包注入循环中加入了一个睡眠,它很好地降低了线程的速度(1Mbps到70Mbps左右),但是如果我想将其限制在1Gbps,那么在睡眠到位的情况下我就无法达到这个速度。现在我知道它可以达到这个速度,因为如果我从所有线程中移除睡眠,它们可以以接近2Gbps的速度注入 所以作为一个测试,我用 usleep(0); 我相信这会使速度再次恢复到最

我有一个多线程系统,其中有x个线程同时向网络发送数据包

这一切都可以很好的工作任何花花公子,但是一些线程我想限制他们的速度,以发送数据包在一定的速度

所以我在我的包注入循环中加入了一个睡眠,它很好地降低了线程的速度(1Mbps到70Mbps左右),但是如果我想将其限制在1Gbps,那么在睡眠到位的情况下我就无法达到这个速度。现在我知道它可以达到这个速度,因为如果我从所有线程中移除睡眠,它们可以以接近2Gbps的速度注入

所以作为一个测试,我用

usleep(0);
我相信这会使速度再次恢复到最大速度,但事实并非如此,它仍然是有限的(仅达到最大速度的1/20左右)。因此,我目前唯一的解释是,即使对于睡眠(0),线程也会产生错误,因此没有线程获得足够的执行时间

所以,很抱歉解释得太长了,但是有没有更好的方法可以让我的线程睡眠而不会造成这样的性能损失呢

我试过usleep和nanosleep,两种方法的效果都一样。所有测试的设置相同,即线程数


System:CentOS、pthreads、g++4.4.6

很可能是函数调用本身减慢了速度(要么是因为函数调用设置和中断,要么是因为调用中的某些内容正在做其他事情,使您放慢了速度)

你可能想考虑一条线:

if (delay > 0) usleep (delay);
因此,如果不需要延迟,则根本不调用该函数

您甚至可以将其封装为:

#define usleepIfNonZero(n) { if (n > 0) usleep (n); }
当然,对宏参数应用了通常的警告(不要传递像
x++
这样的消息,否则会发现它增加了两次)


或者,只需维护数据包计数和用于计算的基本时间,并计算出平均速度。例如:

#define PACKETS_PER_SEC 25

baseTime = now() - 1; // prevent divide by zero later on 
packetCount = 0;
while (1) {
    sendPacket (nextPacket());
    packetCount++;
    secondCount = now() - baseTime;
    while (packetCount / secondCount > PACKETS_PER_SEC) {
        sleep (1);
        secondCount = now() - baseTime;
    }
}

这将自动收敛到每秒数据包数达到25的点,但当然,您可能仍然会发现处理过程不允许您达到全速。

考虑在每次
n
数据包注入时添加
sleep
调用,而不是简单地在每次迭代中添加。这样,您就不会对注入的每个数据包都产生线程切换惩罚,并且您可以以相当细粒度的方式控制睡眠时间。

您说“因此,我目前唯一的解释是,即使对于睡眠(0),线程也会产生,因此没有任何线程获得足够的执行时间。”

如果usleep(…)得到0,那么它没有影响,所以,如果我们传递它0,就不会发生线程上下文切换


您是否验证了usleep(0);真的会引起问题,如果您对这个调用进行注释,一切都会按预期进行?

不要以这种方式依赖睡眠来进行节流。你不是在实时系统上

而是将X数据突发发送到您希望发送X数据/时间单位的位置,其中时间单位可能是毫秒或类似的东西。然后在发送每一次突发后,计算出你需要多少时间睡眠才能达到你想要的平均带宽并睡眠那么多。不要对最后一次爆发进行计算,而是用高精度计时记录每个爆发的开始时间,并计算在更大的爆发集合上的摊销,比如说最后100次爆发或类似的东西。通过这种方式,您可以平均出上下文切换、系统调用、主发送循环之外的内容以及返回运行进程的延迟中的所有开销


当您使用leep(x)(x!=0)时,您正在让步,并且只会被添加到运行队列中的某个位置,无法保证您在非实时系统上再次运行进程的速度有多快。因此,您必须随着时间的推移分摊这些开销差异。

上下文切换(让一个线程离开处理器去另一个线程)是一件昂贵的事情。你确定没有线程切换(例如使用优先级队列)就无法解决问题吗?@thiton我以前没有使用过优先级队列,但我肯定会研究是否可以使用它-谢谢,我确实实现了这一点,如果我只想在每个线程上获得最大速度,那么它非常有效,但是如果我想以任何方式限制线程速度,那么它仍然是一个问题。不过还是要谢谢你!谢谢你的编辑,这似乎也是一个好主意,我可以试试看会发生什么!我只是想说,你的解决方案真的很好!真不敢相信我一开始没想到会这么做:)