У меня есть сервер, на котором в основном запущен сценарий Ruby. Поскольку Ruby (2.7) имеет GIL, он является однопоточным.
Мой компьютер (сервер) имеет двухъядерный процессор Intel i3, но из-за гиперпоточности я вижу 4 ядра. Ruby использует только 25% ЦП при большой нагрузке. Я хотел увидеть, приносит ли отключение гиперпоточности пользу языку программирования, который работает в одном потоке.
Кроме того, на моем сервере работает очень минимальная среда рабочего стола, и он не использует более 2% ЦП. Поэтому я хотел сделать большую часть ресурсов доступной для Ruby. Я провел тест, чтобы увидеть, действительно ли я получаю повышение производительности за счет отключения гиперпоточности.
Я написал простой сценарий Ruby, который запускает цикл while и добавляет значение счетчика цикла с другой переменной. Эта программа должна использовать 100% ядра ЦП:
#!/usr/bin/env ruby
$-v = true
LOOPS = ENV['N'].to_i.then { |x| x < 1 ? 100_000_000 : x } + 1
i, j, t = 0, 0, Time.now
puts "Counting till #{LOOPS - 1} and adding values to V..."
while (i += 1) < LOOPS
if i % 10000 == 0
e = Time.now - t
r = LOOPS.*(e)./(i).-(e).round(2)
print "\e[2KN: #{i} | Done: #{i.*(100) / LOOPS}% | Elapsed: #{e.round(2)}s | Estimated Rem: #{r}s\r"
end
j += i
end
puts "\nV = #{j}\nTime: #{(Time.now).-(t).round(2)}s"
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.55s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.55s
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.54s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.54s
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.67s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.67s
gnome-system-monitor сообщил о 25% загрузке процессора Ruby во время выполнения теста.
[ # echo 0 | tee /sys/devices/system/cpu/cpu{2,3}/online
используется для отключения гиперпотоков]
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.72s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.72s
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.54s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.54s
⮚ ruby p.rb
Counting till 100000000 and adding values to V...
N: 100000000 | Done: 99% | Elapsed: 4.56s | Estimated Rem: 0.0s
V = 5000000050000000
Time: 4.56s
gnome-system-monitor сообщил о 50% загрузке процессора Ruby во время выполнения теста.
Я даже провел тест на своем ноутбуке, который занимает примерно в два раза больше времени, чем на моем компьютере. Но результат идентичен: отключение гиперпоточности не помогает процессу улучшиться. И что еще хуже, мой ноутбук становится немного медленнее при многозадачности.
Таким образом, в режиме без гиперпоточности Ruby использовал в 2 раза больше мощности процессора по сравнению с режимом с гиперпоточностью. Но почему на выполнение одной и той же задачи по-прежнему требовалось столько же времени?
Ваша программа Ruby сделала не использовать в 2 раза больше процессорного времени при работе с отключенным HT. Скорее, поскольку он максимизирует одно ядро из двух общих ядер, gnome-system-monitor
сообщит об использовании как 50%. Если из-за HT система сообщает об общем количестве четырех ядер, одно ядро из четырех будет 25%.
Отключение HT привело к большему разбросу ваших результатов, потому что было доступно меньше ресурсов: последние ядра Intel (или AMD) довольно широки, поэтому дополнительные потоки часто полезны для увеличения совокупной производительности на 10-20%. Если во время тестовых прогонов автоматически выполнялся какой-либо фоновый процесс, система без HT склонна к большей дисперсии и снижению общей пропускной способности.
Я хотел увидеть, приносит ли отключение гиперпоточности пользу языку программирования, который работает в одном потоке.
Я не знаю, как сокращение количества ядер может улучшить производительность даже для однопоточного приложения. Когда гиперпоточность включена, ваш процессор работает с 4 виртуальными ядрами. Однопоточное приложение, использующее весь возможный ЦП, будет использовать 25% доступного ЦП. Когда вы отключили гиперпоточность, вы уменьшили количество ядер до 2. Теперь это однопоточное приложение может использовать 50% доступного процессора.
Ruby не использует в 2 раза больше ЦП, это то, что у вас есть 1/2 ЦП, когда вы отключите гиперпоточность. Если у вас есть большая чашка, наполненная водой на 1/4, и вы наливаете ее в меньшую чашку, которая становится наполовину наполненной водой, у вас все равно остается то же количество воды.
Я даже провел тест на своем ноутбуке, который занимает примерно в два раза больше времени, чем на моем компьютере. Но результат идентичен: отключение гиперпоточности не помогает процессу улучшиться. И что еще хуже, мой ноутбук становится немного медленнее при многозадачности.
Да, вы забираете примерно половину мощности вашего процессора. Это также может замедлить работу потока Ruby. Допустим, у вас есть 3 потока, которые хотят работать одновременно в дополнение к потоку Ruby. Если вы сократите количество виртуальных ядер до 2, более вероятно, что ваш поток Ruby будет приостановлен хотя бы немного, чтобы дать другому потоку время.