Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux.
И, вот, на какую проблему я наткнулся.
Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Kubyshev Andrey, Вы писали:
KA>Здравствуйте, Vladimir Davydov, Вы писали:
KA>Esli eto u tebya serioznyi project, obrati vnimanie na www.rtlinux.com — real time linux.
Na samom dele ee "luchshest'" dovol'no sporna. Ee izvechnymi nedostatkami yavlyautsya
1. Platnost' dlya commercial usage,
2. Medlennoe razvitie (za 2 goda v nei ne pribavilos' nichego new)
3. Razlichnye bottlenecki v systeme tipa neeffektivnoe disk I/O na kotorye developery prosto zabili.
vse eto ya podcherpnul chitaya newsgroups na news.qnx.com
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
10 мс это размер одного кванта времени выделяемого приложению.
обычно функции типа sleep() вызывают переключение контекста задачи, и вообще в многозадачных системах
как-то не принятно полагаться на выделение квантов в точно указанное время,
лучше просто брать текущий отсчет gettimeofday() он достаточно точный, т.е. по сути это
скорректированный пентиум-каунтер.
если я правильно помню, то у nanospeel() есть интересная фича — при маленьких
величинах задержки там работает просто калиброванный пустой цикл, а переключения контекстов
не происходит.
как вариант можно поглядеть в сорцы линуксового кернела на предмет константы HZ,
можно попробовать немного поуменьшить размер кванта времени.
Re[2]: Дискретность задержки usleep() и nanosleep() под Linu
Здравствуйте, maxp, Вы писали:
M>Здравствуйте, Vladimir Davydov, Вы писали:
M>10 мс это размер одного кванта времени выделяемого приложению.
M>обычно функции типа sleep() вызывают переключение контекста задачи, и вообще в многозадачных системах M>как-то не принятно полагаться на выделение квантов в точно указанное время, M>лучше просто брать текущий отсчет gettimeofday() он достаточно точный, т.е. по сути это M>скорректированный пентиум-каунтер.
Сделал вот так:
void musleep(int usec)
{
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
do gettimeofday(&tv2, NULL);
while ((tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec) < usec);
}
Работает правильно. Но самый большой недостаток этого метода --
это то, что даже один запущенный экземпляр этой функции забирает 100% CPU.
С трудом представляю себе, что они намеряют, если их будет запущено
одновременно 1000 штук.
Re[3]: Дискретность задержки usleep() и nanosleep() под Linu
Здравствуйте, Vladimir Davydov, Вы писали:
M>>10 мс это размер одного кванта времени выделяемого приложению.
M>>обычно функции типа sleep() вызывают переключение контекста задачи, и вообще в многозадачных системах M>>как-то не принятно полагаться на выделение квантов в точно указанное время, M>>лучше просто брать текущий отсчет gettimeofday() он достаточно точный, т.е. по сути это M>>скорректированный пентиум-каунтер.
VD>Сделал вот так:
void musleep(int usec)
{
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
do gettimeofday(&tv2, NULL);
while ((tv2.tv_sec-tv1.tv_sec)*1000000+(tv2.tv_usec-tv1.tv_usec) < usec);
}
VD>Работает правильно. Но самый большой недостаток этого метода -- VD>это то, что даже один запущенный экземпляр этой функции забирает 100% CPU. VD>С трудом представляю себе, что они намеряют, если их будет запущено VD>одновременно 1000 штук.
такая ф-ция будет иметь ту же грануляцию по тикам, когда будет запущено
еще что-то подобное.
ты просто подумай как на одном процессоре выполняются разные задачи.
в данном случае schedlue() будет происходить во время gettimeofday()
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. VD>И скорость плавно отрегулировать не удается.
Ну о какой плавности можно говорить в дискретном мире? Всё определяется степенью дискретности. К тому же как бы "плавно" не передавались данные от источника, всегда наложит свой отпечаток среда передачи, поэтому к месту назначения они могут прийти совсем не так уж и "плавно" Я так понимаю, что речь идёт о передаче пакетов по сети? Но в принципе, это касается не только сети?
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
А вообще изначальная задача-то какая была?
Именно передавать пакеты с определёнными интервалами или влиять на скорость прохождения, пропускную способность?
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
В свое время я читал статью об использовании local APIC таймера для создания точных (с разрешением в микросекунду) задержек ("m-second precision timer support for Linux kernel" Uwe Walter, Vincent Oberle). Не знаю включили ли эту идею в новые ядра, а если и нет, то для старых должен быть доступен патч, на котором они проводили тестирование QoS.
Это, конечно, если приложение для x86, точнее даже P6.
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
Вроде бы я уже писал... Или это про Солярис было?
Выдержка из man select:
В некоторых программах select вызывается с тремя пустыми наборами файлов, n равным нулю, и ненулевым значением time-
out, что является довольно переносимым способом сделать задержку с миллисекундной точностью.
... << Павел Фомичев [Музыка Эльфов] Листопад >> ...
Re[2]: Дискретность задержки usleep() и nanosleep() под Linu
Здравствуйте, m.a.g., Вы писали:
MAG>Здравствуйте, Vladimir Davydov, Вы писали:
VD>>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
MAG>Вроде бы я уже писал... Или это про Солярис было?
MAG>Выдержка из man select: MAG>
MAG> В некоторых программах select вызывается с тремя пустыми наборами файлов, n равным нулю, и ненулевым значением time-
MAG> out, что является довольно переносимым способом сделать задержку с миллисекундной точностью.
Вообще-то проблема несколько глубже. Все ОС, которые не являются ОС реального времени гарантируют лишь то, что обработчик получит управление после истечения нужного времени. В Linux задержки select обрабатываются так:
#define HZ 100
...
if ((unsigned long) sec < MAX_SELECT_SECONDS) {
timeout = ROUND_UP(usec, 1000000/HZ);
timeout += sec * (unsigned long) HZ;
}
далее при необходимости происходит schedule_timeout (timeout).
Re[3]: Дискретность задержки usleep() и nanosleep() под Linu
Здравствуйте, Murr, Вы писали:
M>Вообще-то проблема несколько глубже. Все ОС, которые не являются ОС реального времени гарантируют лишь то, что обработчик получит управление после истечения нужного времени.
Ну, это общая проблема не RT-осей. Если нужна точность, то нжуно менять ось...
... << DDT [] track13.mp3 >> ...
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
В Linux-е nanosleep() с задержкой до 2мс выполняется циклом задерки (100% CPU на этот период) и с точностью 1/HZ секунд (HZ=100 для PC) для большего периода.
Более-менее точную задержку можно сделать так: сначала nanosleep на ((n/10)*10)мс, а затем (n%5) раз вызвать nanosleep на 2мс и затем (n&1) раз на 1мс.
Нагрузка на проц значительно уменьшится, но для нескольких таких процессов не подойдет.
Re[3]: Дискретность задержки usleep() и nanosleep() под Linu
От:
Аноним
Дата:
02.02.03 10:19
Оценка:
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Сделал вот так: VD>
VD>Работает правильно. Но самый большой недостаток этого метода -- VD>это то, что даже один запущенный экземпляр этой функции забирает 100% CPU. VD>С трудом представляю себе, что они намеряют, если их будет запущено VD>одновременно 1000 штук.
Если это работает, то точно 17 миллисекунд ты можешь отмерить таким образом: 10 мс -- usleep, а оставшееся время (7 мс) busy wait, своим musleep'ом.
--
Дмитрий
Re: Дискретность задержки usleep() и nanosleep() под Linux
От:
Аноним
Дата:
29.06.06 09:25
Оценка:
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
Владимир, так было ли найдено Вами решение этой проблемы ?
Я пока пробую адаптировать APIC таймер под ядро 2.6.
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
Хм, тоже столкнулся с этой задачей, правда пока решение не особо критично. Однако возникает вопрос: зачем usleep принимает аргумент в микросекундах, если может обеспечить точность лишь 10мс?
Re[2]: Дискретность задержки usleep() и nanosleep() под Linu
Здравствуйте, Zline, Вы писали:
Z>Хм, тоже столкнулся с этой задачей, правда пока решение не особо критично. Однако возникает вопрос: зачем usleep принимает аргумент в микросекундах, если может обеспечить точность лишь 10мс?
Вы удивитесь, но есть еще nanosleep()
А аргументы у них такие, чтобы соответствовать стандартам: usleep — 4.3BSD, nanosleep — POSIX.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[2]: Дискретность задержки usleep() и nanosleep() под Linu
Давно не ковырялся в Linux, примерно с того года, юак начался топик
Но, помнится была такая пересенная HZ в ядре — которая как раз и регулировала кванты, тогда, на 2.4 по дефолту на x86 было значения для 10 миллисек, НО был lowlatency patch который снижал, и прилично latency, попробуйте поиграть с ним, если найдете.
На тот момент, в ядре обычного, т.е. не rtLinux не было, да и не могло быть, способа, который бы что-либо гарантирова в части временных задержек — хоть что-то.
Должен заметить, что была очередm в ядре, задачи из которой выполнялись ASAP, но опять же — никаких гарантий на время, да, это быстрей 10 миллисек.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Дискретность задержки usleep() и nanosleep() под Linux
Здравствуйте, Vladimir Davydov, Вы писали:
VD>Написал, вот, программку, передающую данные в виде пакетов с заданной скоростью. Заданную скорость задаю путем внесения задержек между пакетами. Задержки делаю с помощью функции usleep(). Запускаю я эту программку под Linux. VD>И, вот, на какую проблему я наткнулся. VD>Скорость регулируется скачкообразно, так как usleep() и nanosleep() имеют дискретность задержки в 10 миллисекунд. То есть, нужно, например, сделать задержку 17 мс, а получается только или 10, или 20. И скорость плавно отрегулировать не удается.
VD>Подскажите, пожалуйста, как цивилизованным путем (без 100% загрузки CPU на время задержки) можно добиться задержки с меньшей дискретностью ?
Решил проверить точность функции usleep с помощью такой програмы:
Слева — значение в миллисекундах, переданное usleep'у. Справа — продолжительность задержки, в микросекундах, замеренная с помощью gettimeofday, завязанной на внутренний таймер с частотой порядка 1.2МГц, т.е. имхо весьма точное значение.
(замер производится 10 раз чтобы вычислить более-менее среднее значение)
и вот результат на Linux debian 2.4.27-2-386:
Либо я где-то ошибся, либо имхо результаты отвратительны. Тут даже не 10мс, тут все 15мс ошибки.
для сравнения решил проверить виндовую Sleep аналогичной программой, время замерял с помощью QueryPerformanceCounter, заметил любопытную закономерность — на процессорах intel точность порядка 1мс! :
Всвязи с вышесказанным решил делать некоторую калибровку в софтинах, юзающих эти функции с малыми задержками (< 50ms). Или все-таки мои выводы неверны и где-то я ошибся?
зы. и как винде удается достичь точности в 1мс (пусть и только на интеловских процах)?