我有一个调度程序,无休止地执行 n 操作。每个操作都计划在将来 x 秒。当某个操作完成后,会在之前计划的时间之后重新安排另一个 x 秒。每1秒,调度程序“滴答”,执行最多25次因火灾而发生的动作。动作可能需要一秒左右才能完成(尽管这个值应该被视为可变且不可预测的)。
假设 x 是60秒。由于最多同时执行25个操作的限制,当 n 变大时,可以想象调度程序没有时间执行所有 n 操作。 60秒窗口,随着时间的推移,操作将在稍后和稍后执行。这是不可取的,因为在每一个滴答上都有动作要执行,这会增加我系统的负载。保持 x 与保持负载完全不变是不太重要的。
所以我希望实现一个自适应的“障碍”,一个自动应用的软糖因子 h ,当大多数动作“迟到”执行时增加它,并减少它(将其边缘化为它们的默认值为零)当它们看起来和时间一致时。然后,调度程序将安排 x + h 秒'时间的操作,而不是 x 。
在较高的水平上,你会如何处理?你将如何定义“大多数动作被执行得很晚”,你将如何用C ++ 03代码表示/检测它?
更好的是,是否存在一种客观上“有效”的现有知名方法?
答案 0 :(得分:2)
要明确的是,您的目标是避免在有任务的情况下持续高负荷 每个滴答,而不是旨在最小化调度延迟。 相应地,在考虑软糖时应该考虑的指标 因素是负荷,而不是迟到。
如果你完全了解系统 - 任务的数量,他们的 重新安排间隔,执行时间的分配 - 你原则上可以准确地解决一个可以给你的差点值 繁忙时的平均目标负载,或者说,只会超过目标负载 繁忙的时候,有10%的时间,等等。
另一方面,如果此信息不可用或无法预测, 你需要一种适应性的方法。
这种事情的一般理论是control theory,它可以得到 非常介入。从广义上讲,启发式是:如果负载小于 门槛,我们有一个积极的障碍,减少差点;如果负载是 超过门槛,增加差点。
差点应该是成比例的,而不是额外的:例如, 我们知道我们一直在超载10%,如果我们,那么我们就是正确的目标 在工作安排上应用了10%的比例延迟。也就是说,我们是 希望应用障碍 factor h ,以便在 xh 安排工作 秒时间而不是 x 。因子1对应于没有障碍。
当我们重载但没有最大超载时,响应则是线性的 在日志中:log(h)= log(load) - log(load_target)。所以最简单的方法 将是:
load = get_current_load();
if (load>load_target) h = load/load_target;
else h = 1.0;
不幸的是,存在最大测量负载,并且线性度下降 这里。线性模型可以扩展到包含累积的 偏离目标负载,以及负载的变化率。 这对应于proportional-integral-derivative controller。 因为这是一个嘈杂的环境(行动有变化 执行时间),回避衍生比特可能是明智之举 这个模型,并坚持比例积分(PI)部分。 当这个模型离散时,我们得到log(h)的表达式 这与当前(日志)过载成正比,加上一个术语 抓住我们做得多么糟糕:
load = get_current_load();
deviation = load > load_target ? log(load/load_target) : 0;
accum += p1 * deviation;
log_h = p2 * deviation + accum;
h = log_h < 0 ? 1.0 : exp(log_h);
除此之外,我们没有对称问题:当我们在下面时 负载目标,但累积的错误项保持高位。 我们可以通过积累负偏差来解决这个问题 同样,但至少限制累积误差 非负,使一段时间合法低负荷 以后不会给我们一张免费通行证:
load = get_current_load();
if (load > 0) {
deviation = log(load/load_target);
accum += p1 * deviation;
if (accum < 0) accum = 0;
if (deviation < 0) deviation = 0;
}
else {
accum = 0;
deviation = 0;
}
log_h = p2 * deviation + accum;
h = log_h < 0 ? 1.0 : exp(log_h);
p2的值将在某处(大致)介于0.5和0.9之间, 留下一些空间来累积误差的影响。 p1的良好值可能约为0.3至0.5倍 延迟时间的倒数,改变所需的步骤数 在h中表现为负载的变化。这可以估计 通过行动的平均重新安排时间。
您可以使用这些参数来获得这种参数 回答你的喜好,或者你可以做一个更忠实的数学 你的调度问题的模型,然后做数学! 参数本身也可以自适应地修改 时间,基于观察到的对负荷变化的反应。
(警告,我还没有在模拟调度程序中尝试过这些片段!)