我有一个循环的指令,例如(伪代码):
for i = 1 to 1000000
// Process the ith input
doSomething(input[i])
end
这需要很长时间才能完成。我想输出一些进展,更重要的是剩余的时间估计给用户,这样他们就可以决定是否应该坐在那里摆弄他们的拇指,去喝咖啡,散步,或者去度过一个星期的假期当算法压缩其数字时,到欧洲。
为简化问题,您可以假设迭代次数很多(例如,大于100,因此您可以在每个百分位数打印进度)。
一种常见的算法是简单地测量上次迭代所花费的时间,然后将其乘以剩余的迭代次数并将其作为输出。如果每次迭代在执行所需的时间内变化很大,则会出现故障。
另一种方法是将自第一次迭代以来经过的时间除以完成的迭代次数,然后将其乘以剩余的迭代次数。如果迭代的持续时间不均匀分布,则会发生故障。例如,如果前几个输入是“困难的”并且在输入数组的末尾变得更容易,则算法将高估剩余时间直到它几乎完成(此时它会略微高估)。
那么,当每次迭代所花费的时间是一个非直接的,任意的函数(这样只需要分析地推导和实现每次迭代的完成时间是不切实际的)时,如何更好地估计剩余时间。迭代纵坐标?
我能想象的两个想法可能是富有成效的研究途径,但此时我无法完全探索自己:
为什么计算密集型解决方案(如拟合方程式)没问题
首先,对于值得讨论的真正大型任务,运行时间可以用几小时或几天来衡量。这些天复杂的数学运算需要几毫秒,所以增加的负担也不会很大 - 在上面的例子中,显然doSomething
只需要花费一些数学成本相形见绌,否则我不会那么关心首先估算剩余时间。
其次,例如,可以将迭代迭代到百分位数。然后,不是对“迭代完成与所花费的时间”的数据集进行操作,而是估计器将对“完成百分比与所花费的时间”的数据集进行操作,该数据集具有至多100个数据点。这提供了进一步的复杂性:假设您的任务需要一天或更长时间才能完成。仅在每个百分比完成时估计剩余时间意味着对估计器函数的100个评估。当你已经花了一天时间,估计剩余时间的时间超过一分半并不是什么大不了的事,但这已经给你一个1秒的窗口来拟合方程式而不是 - 1秒很多在现代系统上进行数学运算的时间。因此,我欢迎计算密集型解决方案。
tl; dr:如何为非常冗长的任务过度设计准确的剩余时间估算函数。
答案 0 :(得分:2)
如果你想获得一致好的预测,那么第二种方法(拟合和推断)可能做得最好 - 但仅假设拟合函数与作为函数的处理时间的真实依赖性的合理匹配指数。例如,如果f(n)是O(n ^ 2)算法,则预测
的时间for i = 1 to N
f(i)
需要大约k * N ^ 3的时间来解决。因此拟合立方与总时间应提供相当好的近似,但拟合二次或指数可能比简单的百分比完成近似更差。同样,如果f是O(2 ^ n),那么任何多项式拟合都会大大低估剩余时间。这一切都假设N足够大,真正的O(n ^ 2)行为占主导地位。
因此,虽然精心选择的拟合函数应该能够准确地预测剩余时间,但通用预测函数不太可能有用。
答案 1 :(得分:1)
除了Penguino的算法:你可能想要拟合log(n)和log(f(n)),而不是拟合n和f(n)。只要你的复杂性是多项式,这就行了。
答案 2 :(得分:-1)
之前我做过类似的事。我发现的最简单的方法是创建一个非常准确的时间估计(再次,在p代码中):
initTime = getTime()
for i = 0 to maxIter
doSomething()
remainTime = convertToHoursMinutes(((getTime - initTime)/i)*maxIter)
next
这样,你每次迭代都会得到'平均'时间,经过30-50次迭代后,你的用户可能对剩余时间有了一个很好的了解(最终,中心极限定理开始发挥作用)。