无论系统的其余部分是否空闲,任务都必须接收相同的资源分配,不能再多。目的是无论系统上的其他负载如何,都能在可预测的时间内完成任务。
尝试系统,使用CPUAllocation
和CPUQuota
,搭配一个简单的单线程测试程序表明,当运行的次数较少时,花费的时间会更长。
在不受限制的情况下,该过程需要 15 秒才能运行。当限制为一个 CPU 的 20% 时,运行 5 个实例每个大约需要 75 秒,符合预期(因为5*15=75
)。
这导致当限制为一个 CPU 的 20% 时,无论实例数量有多少(一个 CPU 最多 5 个),每个实例都需要 75 秒才能运行。
然而,运行越来越少的实例(留下一些未使用的 CPU 容量)所花费的时间比预期的 75 秒要长,并且运行单个实例(没有其他系统负载)需要 250 秒。
这是没有意义的:单个进程应该花费 75 秒,与运行 5 个进程花费的时间相同。
如果运行另一个进程来“吸收”未使用的 CPU 容量,则预期 75 秒内完成的实例数量会减少。
为什么会出现这种情况?
和
有没有更合适的方法来达到预期的效果,确保无论其他系统负载如何,任务都需要相似的时间来执行?
(系统在实验时使用,但直接使用cgroups可能更合适,也许更合适)。
用于测试的systemd服务单元文件
$ cat /etc/systemd/system/cputest\@.service
[Service]
User=nobody
SyslogIdentifier=cputest
ExecStart=/usr/local/bin/cputest.rb
CPUAffinity=1
CPUQuota=20%
测试程序是故意低效的Pi 的算法:
$ cat cat /usr/local/bin/cputest.rb
#!/usr/bin/ruby
PRECISION = 10 ** 8 # decimal places
PI_TARGET = (Math::PI * PRECISION).to_i
d = neg = 1
pi_test = pi = 0
START = Time.now.to_f
def elapsed() Time.now.to_f - START end
while pi_test != PI_TARGET do
pi += neg * (4.0/d)
pi_test = (pi * PRECISION).to_i
d+=2
neg*=-1
end
puts elapsed()
运行与
for i in {1..4}; do sudo systemctl start cputest@$i; done
收集输出
sudo journalctl -xft cputest
答案1
看来,未充分利用的 CPU 的缓慢是由于 CPU 应用的省电技术造成的。当CPU达到最大时,允许涡轮增压并且跑得更快。当上限为 20% 时,它并未达到最大,因此运行速度会较慢。
我正在一台具有这些 CPU 的笔记本电脑上进行开发。我找到了一台服务器并再次运行测试并得到了我期望的结果。
除了尝试“性能”调节器之外,我没有进行任何其他测试,但这没有什么区别。我还没有进入 BIOS 设置或类似的东西。我认为在限制旨在节省电量的系统上进程的 cpu 时,需要注意这种行为。