К>Лучше исходить из средней скорости за последние несколько секунд. Для этого заводится окно измерений p(t) с постоянной или переменной частотой сэмплирования. Размер окна следует выбирать так, чтобы он охватывал несколько ступенек.
Кстати, в фин. анализе иногда используется взвешенное скользящее среднее (EMA), которое позволяет вообще обойтись без запоминания всех значений окна — требуется помнить только одно предыдущее значение:
http://en.wikipedia.org/wiki/Exponential_moving_average#Exponential_moving_average
ИМХО будет очень красиво работать!
Здравствуйте, <Аноним>, Вы писали:
А>Что я делаю не так?
Нужно определиться с двумя вещами:
— метод измерения
— метод экстраполяции
У тебя есть зависимость p<->t, показывающая процент выполнения и потраченное время. p(0)=0, p(t_end)=100%.
(Можно пересчитать проценты в байты — это дела не меняет).
Можно предположить, что зависимость линейна, но на деле это не так: примешиваются и неровности скорости выполнения, и взаимодействие выполнения с измерением.
Например, фактическая p(t) — это одинаковые ступеньки вдоль линейной асимптоты, а период измерений не совпал с периодом ступенек. В измеренной функции будут биения.
Поэтому постоянное сэмплирование по таймеру — не всегда хорошая затея. А частота измерений 4 раза в секунду — вообще не оправдана.
Ну ладно, вернёмся к экстраполяции.
p(t) = p_now+v_now*(t-t_now)
решаем уравнение ? t_end : p(t_end)=100%
t_end = t_now+(100%-p_now)/v_now
Тут есть две крайности:
1) Моментальная скорость. Проблема в том, что моментальная скорость постоянно прыгает — и по причине внезапных разгонов/тормозов, и из-за ступенчатой природы выполнения.
Как следствие, t_end станет метаться то в "почти сейчас", то в "никогда потом".
2) Средняя скорость от начала работы: v_now=p_now/t_now. Если в начале были тормоза, то ожидаемое время будет постоянно завышено, а если тормоза возникли сейчас, — то наоборот, занижено.
Лучше исходить из средней скорости за последние несколько секунд. Для этого заводится окно измерений p(t) с постоянной или переменной частотой сэмплирования. Размер окна следует выбирать так, чтобы он охватывал несколько ступенек.
Если скорость выполнения упала, и в окне много повторяющихся значений p(t), то можно понизить частоту, при этом длительность окна вырастет, а объём памяти сохранится.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Добрый вечер.
Пишу программу которая выполняет ф-ию заливки стуктуры файлов с одного место в другое (к примеру нужно переписать все файлы из директории c:\Windows\ в указанную директорию). Задача в том что я не могу правильно написать алгоритм подсчета времени.
function TFormCopy.CalculateTime(newReaded: Int64; maxSize : Int64): Int64;
var
nowTime, timeSpent : Cardinal;
bytePerSec : Integer;
begin
Result := -1;
if newReaded = 0 then Exit;
nowTime := MilliSecondOfTheDay(Now);
if lastTime = 0 then
begin
lastTime := nowTime;
Exit;
end;
timeSpent := nowTime - lastTime;
if timeSpent > 0 then
begin
bytePerSec := newReaded div timeSpent;
if bytePerSec <= 0 then
bytePerSec := 1;
Result := Floor(maxSize - newReaded) div bytePerSec;
end;
lastTime := nowTime;
end;
Эта ф-ия возращает время в секундах. newReaded — сколько байт уже считано всего.
Вызываю эту функцию из диалога в котором подсчитывается для пользователя премерное время завершения, данные беру у Thread'a в котором происходит копирование. Ф-ия вызывается раз в 250 сек. по таймеру.
Что я делаю не так?
Здравствуйте, <Аноним>, Вы писали:
А>Эта ф-ия возращает время в секундах. newReaded — сколько байт уже считано всего.
А>Вызываю эту функцию из диалога в котором подсчитывается для пользователя премерное время завершения, данные беру у Thread'a в котором происходит копирование. Ф-ия вызывается раз в 250 сек. по таймеру.
А>Что я делаю не так?
Что такое newReaded, т.е. сколько прочитано после последнего вызова CalculateTime или сколько всего прочитано в последнем "задании"?
Если первое, то (maxSize — newReaded) больше реального остатке, если второе, то bytePerSec := newReaded div timeSpent больше реальной скорости за последний интервал.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, a18, Вы писали:
a18>Кстати, в фин. анализе иногда используется взвешенное скользящее среднее (EMA), которое позволяет вообще обойтись без запоминания всех значений окна — требуется помнить только одно предыдущее значение:
a18>http://en.wikipedia.org/wiki/Exponential_moving_average#Exponential_moving_average
a18>ИМХО будет очень красиво работать!
Очень интересно!
Правда, остаются вопросы:
— как подобрать альфу
— как интерполировать измерения (ступеньками, трапециями, экспонентами),
чтобы
— уменьшить влияние частоты сэмплирования (поскольку чем выше частота, тем отчётливее получатся ступеньки — хотя наша задача ещё и сгладить их)
— получить приемлемый результат с минимумом дерготни
... << RSDN@Home 1.2.0 alpha rev. 655>>
a18>>Кстати, в фин. анализе иногда используется взвешенное скользящее среднее (EMA), которое позволяет вообще обойтись без запоминания всех значений окна — требуется помнить только одно предыдущее значение:
a18>>http://en.wikipedia.org/wiki/Exponential_moving_average#Exponential_moving_average
a18>>ИМХО будет очень красиво работать!
К>Очень интересно!
К>Правда, остаются вопросы:
К>- как подобрать альфу
К>- как интерполировать измерения (ступеньками, трапециями, экспонентами),
К>чтобы
К>- уменьшить влияние частоты сэмплирования (поскольку чем выше частота, тем отчётливее получатся ступеньки — хотя наша задача ещё и сгладить их)
К>- получить приемлемый результат с минимумом дерготни
По ссылкам там, оказывается, ещё одна подобная статья есть:
http://en.wikipedia.org/wiki/Exponential_smoothing#The_exponential_moving_average
... с диагнозом: "There is no formally correct procedure for choosing a"
На практике обычно берут, как и написано в первой статье, alpha = 2/(N+1), где N — период обычной скользящей средней (SMA), поведение которой нас устраивает.
По ощущениям, чтобы пользователю было интересно наблюдать за результатами предсказания, можно сделать частоту измерений 1 раз в секунду и N взять порядка 10..50 — для копирования файлов должно быть приемлемо. Кстати, при большИх N ещё есть проблема начального выплеска — если первое измерение будет неадекватно большим (а для случая копирования файлов это весьма вероятно), то функция потом будет слишком долго "приходить в себя". Возможно, тут оправдано взять в качестве первого значения не x0, а просто чистый 0.