Как распределить процессы во времени, получая минимальное количество " коллизий"
Я разрабатываю планировщик для встроенной системы. Этот планировщик будет вызывать каждый процесс каждые X миллисекунд; на этот раз можно настроить отдельно для каждого процесса, конечно.
все закодировано и вызывает каждый процесс так, как должно; проблема, с которой я сталкиваюсь, заключается в следующем: Представьте, что я установил 4 процесса, которые будут вызываться каждые 10, 15, 5 и 30 миллисекунд соответственно:
A: 10ms
B: 15ms
C: 5ms
D: 30ms
результирующий вызов с течением времени будет:
A |
A B A B |
C C C C C C C | processes being called
D |
----------------------------------
0 5 10 15 20 25 30 35... ms
проблема что при достижении 30 мс все процессы вызываются в один и тот же момент (один за другим), и это может задержать правильное выполнение отсюда.
Это можно решить, добавив задержку к каждому процессу (но сохранив его вызывающую частоту), поэтому частоты перестают быть кратными друг другу. Моя проблема в том, что я не знаю, как рассчитать задержку для применения к каждому процессу, чтобы количество столкновений было сведено к минимуму.
есть ли известный алгоритм для этого, или какое-то математическое руководство?
спасибо.
4 ответов
учитывая набор интервалов, вы можете найти время, когда начальные времена совпадут (при условии отсутствия смещений), найдя наименьшее общее кратное Как упоминалось Джейсоном в комментарии к вашему сообщению. Вы можете найти LCM, выполнив простую факторизацию интервалов для набора задач.
кажется, что наибольший общий делитель (или наибольший общий коэффициент GCF) может быть наиболее полезным числом для вычисления. Это число даст вы интервал, на котором повторяется будет. В вашем примере GCF равен 5. С GCF 5, возможно добавить начальное смещение 1, 2, 3, etc. к каждой задаче, чтобы избежать перекрытия времени начала. Таким образом, с GCF 5 Вы можете иметь до 5 задач, которые имеют начальное время, которое никогда не будет перекрываться. С GCF 20 вы можете запланировать до 20 задач без перекрытия времени начала. Если две (или более) задачи относительно простые (GCF=1), то перекрытие определенно не произойдет важно, какое смещение вы используете для этих задач, если интервалы никогда не меняются.
нет идеального решения для этого, они будут сталкиваться время от времени. Я бы предложил добавить крошечное (0,01-0,1 мс) случайное значение к длине цикла, поэтому в долгосрочной перспективе они будут очень редко вызываться одновременно.
кроме того, если у вас есть гранулярность планировщика 5ms, первый поток всегда вызывается в X+1ms, второй-в X+2, e.т. c, так что всегда гарантируется 1 мс бесперебойного запуска (если у вас есть 10 потоков, то это будет X+0.5, X+1, X+1.5). Но это может получить довольно сложно реализовать.
эта проблема напрямую связана с областью алгоритмов программирования и планирования в реальном времени. В колледже я брал уроки по этому предмету, и если я хорошо помню,Rate-монотонное планирование - это тот алгоритм, который вы ищете.
идея заключается в том, что вы назначаете приоритеты заданиям, которые обратно пропорциональны их периоду, т. е. чем меньше период, тем выше приоритет. Но это работает лучше, если вы можете прервать свою работу и возобновить их потом.
есть и другие альтернативы, хотя, вроде бы EDF (первый крайний срок), но это алгоритмы динамического планирования (т. е. приоритеты назначаются во время выполнения).
простым решением является изменение расписания, в котором вы вызываете подпрограммы. Т. е. вместо 5, 10, 15 и 30 мс, можете ли вы жить, например, с 5, 15, 15 и 30? Затем вы можете использовать следующий шаблон: (A=5 ms proc, B, C=15 ms proc, D=30 ms proc):
AAAAAAAAAAAAAAAAAAAA ...
B B B B B B B ...
C C C C C C C ...
D D D ...
Я уверен, что вы можете обобщить эту идею, но она работает только в том случае, если вы действительно можете изменить статические интервалы.
Если вы не можете изменить интервалы, а также вам нужно строго им подчиняться, то я вас добр не повезло, так как нет параметров для изменения:)