Linux Kernel- task_h_load
Я пытаюсь понять, что происходит во время функции load_balance
.
Я проверяю версию 3.14, но я также взглянул на версию 4.3, так как мне сказали, что механизм был изменен и немного более ясен в этой версии.
в v3.14 вызов осуществляется из move_tasks
в v4.3 вызов осуществляется из detach_tasks
из того, что я вижу, это одна и та же функция, но только с другим именем.
Эта функция перемещает задачи из одной очереди в другую в соответствии с параметром env->balance
.
Я не понимаю, что/как вычисляется нагрузка в task_h_load
.
Кто-нибудь знает, что представляет элемент загрузки и как он вычисляется в функции task_h_load
?
Ответы
Ответ 1
CFS содержит дерево "планирующих сущностей". Каждый объект планирования может иметь свое собственное дерево и т.д. Рекурсивным образом...
(Это полезно, например, для группировки всех процессов конкретного пользователя в один объект планирования, что предотвращает пользователя, у которого много задач, потребляет больше времени процессора, чем пользователи с меньшим количеством процессов).
task_h_load - означает " иерархическая загрузка задачи"
Так как задача может быть вложена в несколько деревьев, то вычисление ее нагрузки не так просто...
static unsigned long task_h_load(struct task_struct *p){
struct cfs_rq *cfs_rq = task_cfbs_rq(p);
update_cfs_rq_h_load(cfs_rq);
return div64_ul(p->se.avg.load_avg * cfs_rq->h_load,
cfs_rq_load_avg(cfs_rq) + 1);
}
В начале cfs_rq
указывает на непосредственное дерево, в котором находится p. Если бы у нас было только два вложенных дерева, тогда вычисление нагрузки p было бы простым:
task_h_load = task_load_in_its_tree * (load_of_immediate_tree/ load_of_containing_tree);
(в то время как direct_tree ссылается на дерево, содержащее задачу, и contains_tree ссылается на дерево, содержащее дерево, содержащее задачу.)
Но это не так. Наше дерево может быть вложенным деревом внутри объекта планирования, который сам по себе является листом в другом дереве.
Итак, первое, что мы делаем, это вызвать update_cfs_rq_h_load(cfs_rq)
, который вычисляет коэффициент иерархической нагрузки для cfs_rq
и всех его потомков (предков): эта функция поднимается до иерархии дерева вплоть до корня и вниз от корня до нашего cfs_rq
при вычислении иерархического коэффициента загрузки для каждого дерева в иерархии.
Вычисление выполняется аналогичным образом:
cfs_rq_h_load = cfs_rq_load_in_its_tree * (load_of_immediate_tree/ load_of_containing_tree)
Итак, наконец, мы имеем дробную нагрузку cfs_rq
, и все, что нам нужно сделать, это вычислить h_load с использованием той же формулы.
task_h_load = task_load_in_its_tree * (load_of_immediate_tree/ load_of_containing_tree)
Ответ 2
Балансировка нагрузки вызывается, если SMP настроен. Linux использует "Полноценный планировщик" (CFS) для планирования каждой задачи, чтобы каждый из них получал "справедливая" доля процессорного времени. CFS использует концепцию красно-черного дерева.
![введите описание изображения здесь]()
Планировщик записывает текущее время, когда задача входит в очередь выполнения. Пока процесс ожидает процессорного времени, его значение "wait" увеличивается на величину, полученную из общего количества задач, находящихся в настоящее время в очереди выполнения и приоритета процесса. Когда процессор выполняет эту задачу, это значение "wait" получает декремент. Если это значение опускается ниже определенного значения, тогда планировщик будет упредить задачу, а другая задача приблизится к выполняемому процессору. CFS всегда стараются сохранить ситуацию идеальной, сохраняя значение "wait" равным нулю.
В linux load_balance
и select_task_rq_fair()
есть две функции, которые выполняют задачу баланса нагрузки.
В простом ключевом слове механизм балансировки нагрузки CFS выгружает занятый CPU на менее занятый или идеальный.
task_h_load
используется для вычисления веса задачи.
То, что я не понимаю, это то, что/как рассчитывается нагрузка в task_h_load. как он вычисляется в функции task_h_load?
Этот весовой коэффициент зависит от хорошего значения процесса.
weighting factor = weight of process with nice value 0 / weight of current task;
где вес приблизительно эквивалентен 1024 * (1.25) ^ (- nice)
Например:
вес 820 для хорошего значения 1
вес 1277 для хорошего значения -1
task_h_load
Для получения дополнительных методов и основ балансировки нагрузки обратитесь к комментарий ядра
task_h_load
используйте update_cfs_rq_h_load
для вычисления иерархической нагрузки очереди выполнения для планирования в режиме реального времени и которые используют cfs_rq_load_avg возвратную среднюю нагрузку runqueue load_avg.
Виртуальное время выполнения - это взвешенное время выполнения задачи на CPU. CFS всегда стараются сохранить this Красно-черное дерево в балансе.
![введите описание изображения здесь]()
< - меньшее значение ----------- значение vruntime -------- большее значение →
Каждая выполняемая задача помещается в самобалансирующееся дерево Red Black на основе vruntime
. Если задача готова к запуску (значит, задача не ждет какого-либо ресурса), она помещается в дерево. Если задание ожидает какой-то ресурс (ожидающий ввода-вывода), он удаляется. Задачи, у которых меньше времени обработки (меньше vruntime
), находятся в левой части дерева, а задачи с большим временем обработки - правая сторона дерева.
Левое node имеет наименьшее значение ключа (для CFS это задача с более высоким приоритетом). Для балансировки красного черного дерева нужна операция O (lgN), чтобы перейти влево node. Планировщик кэширует это значение в rb_leftmost
. Извлекая только это значение, планировщик определяет, какая задача будет выполняться следующей
Этот баланс нагрузки используется только для нереальной задачи для реального времени используются операции push-pull, которые разрабатываются Стивеном Ростедтом и Грегори Хаскинс
Еще одна вещь о CFS также полезна при планировании Fair Group. Рассматривайте ниже рисунка
![введите описание изображения здесь]()
move_task
просто пытается переместить взвешенную нагрузку на дисбаланс (средство после вычисления коэффициента нагрузки, как показано выше) от предприятий до this_rq
. Он пытается равным балансу нагрузки обеих очередей запуска, так что оба могут сэкономить "честное" время процессора.
detach_task
отделить задачу для миграции, указанной в указателе env
ядра linux.
detach_one_task
пытается удалить только одну задачу из env- > src_rq.
detach_tasks()
пытается отделить от взвешенной нагрузки с дисбалансом от
busiest_rq
. И он возвращает количество отложенных заданий или же ноль, если не удается отсоединить.
Чтобы прикрепить эту удаленную задачу к новой rq
(очередь запуска), attach_task, attach_one_task,attach_tasks
используется в соответствии с ситуацией.
Новая предупредительная проверка lockdep_assert_held()
введена в detach_tasks
, которая отсутствовала в move_tasks
В многопроцессорном режиме задача легко переносить так легко, поэтому cfs выполняет балансировку нагрузки на уровне домена, как показано ниже:
![введите описание изображения здесь]()
Чтобы все это понять, я хотел бы, чтобы вы прошли следующую ссылку
Я специально прочитал всю эту документацию, чтобы ответить на ваш вопрос. Надеюсь, вы не против комментировать, если что-то не хватает.