2010-11-20 2 views
1

Есть ли способ ограничить итерации в единицу времени? Например, у меня есть цикл вроде этого:Предельные итерации за единицу времени

for (int i = 0; i < 100000; i++) 
{ 
    // do stuff 
} 

Я хочу, чтобы ограничить цикл выше, так что будет не более 30 итераций в секунду.

Мне также хотелось бы, чтобы итерации были равномерно размещены на временной шкале, поэтому не должно быть примерно 30 итераций в первые 0,4 с, а затем ждать 0,6 с.

Возможно ли это? Он не должен быть полностью точным (хотя тем точнее он будет лучше).

+0

Зачем вы хотите это сделать? – fredoverflow

+0

Nop, вы не можете этого сделать. Дело в том, что вам нужно искать «таймеры» и пусть он запускает ваш код каждый (1/30) с, например. – AraK

+0

@FredOverflow Моя программа работает очень быстро. Он отправляет данные по Wi-Fi в другую программу, которая не достаточно быстра, чтобы обрабатывать их с текущей скоростью. –

ответ

8

@FredOverflow Моя программа работает очень быстро. Он отправляет данные по Wi-Fi в другую программу, которая не является достаточно быстрой, чтобы обрабатывать их по текущему курсу . - Richard Knop

Возможно, у вас, вероятно, есть программа, по которой вы отправляете данные, чтобы отправить подтверждение, когда оно закончило получение последнего фрагмента данных, которые вы отправили, затем отправьте следующий фрагмент. Все остальное будет просто приводить вас к разочарованиям по мере изменения обстоятельств.

+1

Это правильный ответ «управление потоком». Использование таймеров для управления потоком будет подвержено ошибкам и наложит искусственный колпачок на скорость передачи данных. – Blastfurnace

2

Предположим, у вас есть хороший Now() функцию (GetTickCount() это плохой пример, это ОС специфичны и имеет плохую точность):

for (int i = 0; i < 1000; i++){ 
    DWORD have_to_sleep_until = GetTickCount() + EXPECTED_ITERATION_TIME_MS; 
    // do stuff 
    Sleep(max(0, have_to_sleep_until - GetTickCount())); 
}; 
1

Вы можете проверить истекшее время внутри цикла, но это может быть не обычное решение , Поскольку время вычислений полностью зависит от производительности машины и алгоритма, люди оптимизируют ее в течение своего времени разработки (например, для многих программистов требуется не менее 25-30 кадров в секунду для правильной плавной анимации).

1

Самый простой способ (для окон) использовать QueryPerformanceCounter(). Ниже приведен псевдокод.

QueryPerformanceFrequency(&freq) 
timeWanted = 1.0/30.0 //time per iteration if 30 iterations/sec 
for i 
    QueryPerf(count1) 
    do stuff 
    queryPerf(count2) 
    timeElapsed = (double)(c2 - c1) * (double)(1e3)/double(freq) //time in milliseconds 
    timeDiff = timeWanted - timeElapsed 
    if (timeDiff > 0) 
     QueryPerf(c3) 
     QueryPerf(c4) 
     while ((double)(c4 - c3) * (double)(1e3)/double(freq) < timeDiff) 
      queryPerf(c4) 
end for 

EDIT: Вы должны убедиться, что «делать такие вещи» область занимает меньше времени, чем ваш фреймрейтом или иначе это не имеет значения. Кроме того, вместо 1e3 в миллисекундах вы можете пройти весь путь до наносекунд, если вы сделаете 1e9 (если вы хотите получить такую ​​точность)

ПРЕДУПРЕЖДЕНИЕ ... это съест ваш процессор, но даст вам хорошее «программное обеспечение». Делайте это в отдельном потоке (и только если у вас есть более одного процессора), так что любая заглушка не будет заблокирована. Вы можете поставить условное условие, чтобы остановить цикл, если это многопоточное приложение.

+0

Я использую этот метод, когда очень важно иметь точное время. Функции сна меняются ДРАТИЧЕСКИ и не могут дать очень хорошие сроки, если вам нужно, чтобы они были очень точными. – g19fanatic

1

@FredOverflow Моя программа работает очень быстро. Он отправляет данные по Wi-Fi в другую программу, которая не достаточно быстра, чтобы обрабатывать их с текущей скоростью. - Richard Knop

Что может понадобиться буфер или очередь на стороне приемника. Поток, который получает сообщения от клиента (например, через сокет), получает сообщение и помещает его в очередь. Фактический потребитель сообщений читает/выскакивает из очереди. Конечно, для вашей очереди необходим контроль параллелизма.

0

Помимо упомянутых способов управления потоком, если вам также необходимо поддерживать точную скорость передачи данных в части отправителя. Обычно это можно сделать так.

E.x. если вы хотите отправить на скорости 10 Мбит/с, создайте таймер интервала 1 мс, чтобы он вызывал предопределенную функцию каждые 1 мс. Затем в функции обработчика таймера, отслеживая 2 статических переменных 1) Время, прошедшее с начала отправки данных 2) Сколько данных в байтах было отправлено до последнего вызова, вы можете легко подсчитать, сколько данных необходимо отправить в текущем вызове (или просто спать и ждать следующего вызова).

Таким образом, вы можете выполнять «потоковой передачи» данных очень стабильным способом с очень маленькой jitterness, и это обычно принято при потоковой передаче видео. Конечно, это также зависит от того, насколько точным является таймер.

Смежные вопросы