четверг, 21 ноября 2013 г.

Почему не стоит использовать больше потоков, чем необходимо?

Существует распространённое мнение, что поскольку у нас много ядер – а в будущем будет ещё больше – мы должны их использовать. Мы просто обязаны найти оптимальные способы их использовать, но лишь потому, что мы можем, не значит, что нам стоит это делать.


Какова наша цель?

Веские причины использовать множество потоков:
  • Производительности одного потока недостаточно.
  • Вы выполнили профилирование своего приложения, чтобы удостовериться в отсутствии других факторов, ограничивающих производительность.
  • Множество потоков улучшает пропускную способность и уменьшает задержки.
То есть, вы должны добавить поток, если он приближает вас к цели.
Аргументы против использования множества потоков:

  • Только потому, что мы можем использовать больше потоков, не значит, что стоит их использовать. Множество потоков усложняет код
  • Есть другие способы ускорить работу приложения. Ваш кэш первого уровня (L1) в 10 раз быстрее, чем кэш третьего уровня (L3), и если вы можете провести больше времени в L1-кэше, оптимизируя использование и доступ к памяти, то добьётесь большей производительности, чем используя все доступные ядра и CPU.
  • Множество потоков способно привести к появлению трудно находимых ошибок, чего нельзя сказать об однопоточном коде.
  • Множество потоков увеличивает потери на синхронизацию, использование неизменяемых объектов вместо повторного использования изменяемых и т.д.
  • Множество потоков обычно увеличивает джиттер и ухудшает показатель производительность в наихудшем случае, даже если типичная производительность лучше.

Одним словом, многопоточность часто приводит к замедлению, нежели ускорению работы программы. Разве что подойти к ней с умом. Два CPU в лучшем случае могут быть вдвое быстрей, но с тем же успехом могут работать вдесятеро медленней, если не проявить осторожность.

Простой пример - вычисление чисел Фибоначчи. Это просто сделать с помощью рекурсивного метода, или создав множество потоков. Таким образом, определение чисел Фибоначчи часто служит примером использования большого количества потоков. Лишь об одном умалчивается: число создаваемых вами потоков равно ответу, то есть растет экспоненциально. Если во время итерирования в одном цикле/потоке на вычисление fib(69) уходит около 4 минут, в случае с множеством потоков та же процедура занимает целую вечность, если не выводит систему из строя.

Вывод

Если вы сосредоточены на создании своей системы, чтобы упростить разработку и сопровождение, вы ищите лёгкое решения проблем. Если оно предполагает, что вы не будете использовать на все 100% пропускную способность сети, дисковое пространство, память или свои CPU -- ничего страшного.


Источник

Комментариев нет:

Отправить комментарий