Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как определить скорость передвижения выполнения кода в мс?
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Система рисования. Печать
zuze
Если в секундах или пол секунды я могу в уме проверить оборот прохождения линии по горизонтали, то меньше уже не могу в уме проверить.
Как это проверить, программно?
zuze
Как я понял надо замерить тики.

Я сделал так:

#include <windows.h>
    
uint start = GetTickCount();
// Рисуем линию
qDebug() << "Time: " << GetTickCount() - start;


Но почему-то 0 выводится?
sidsukana
Самый простой способ
QTime m_time;
m_time.start();

// Замеряемый код

qDebug() << m_time.elapsed();


Точность в мс. Если выводит 0 значит быстрее 1мс.

В микросекундах проверить проблематичней, так как все зависит от тактовой частоты процессора.
lanz
Использовал http://msdn.microsoft.com/ru-ru/library/wi...4(v=vs.85).aspx
Точность очень хорошая.
В интернетах пишут, что есть проблемы со сдвигом счетчика/из-за багованного биоса.
Лично не сталкивался, поэтому врать не буду .)
Если GetTickCount() показывает 0 можно нарисовать например 10000 линий, измерить и поделить, так точность будет даже лучше (т.к. усредняются всякие системные процессы).
zuze
Цитата(sidsukana @ 30.1.2013, 9:18) *
Точность в мс. Если выводит 0 значит быстрее 1мс.


Я по вашему совету сделал так:

QTime m_time;
m_time.start();

if (static_cast<int>(MyRadianToGradus(phi)+0.5) <= 360)
   Line.drawLine(50 + phi*720.0/(2*M_PI), 50, 50 + phi*720.0/(2*M_PI), 542);    // Рисуем линию

if (static_cast<int>(MyRadianToGradus(phi)+0.5) == 360)
   qDebug() << m_time.elapsed();


Линию рисую в переопределении метода paintEvent().
Линия делает оборот за 0.05 секунды или 50 миллисекунд, но выводятся почему-то 0?
Я даже на глаз вижу передвижение линии и это явно не 1 миллисекунда. Передвижение равное 1 миллисекунде я новерно бы глазом и не увидел бы.
lanz
Цитата(zuze @ 30.1.2013, 11:03) *
Линия делает оборот за 0.05 секунды или 50 миллисекунд, но выводятся почему-то 0?


Потому что m_time.start () вызывается заново каждый раз перед рисованием линии. Надо вызвать его один раз, перед началом рисования всех линий.
zuze
Цитата(lanz @ 30.1.2013, 10:41) *
Потому что m_time.start () вызывается заново каждый раз перед рисованием линии. Надо вызвать его один раз, перед началом рисования всех линий.


Я сделал m_time.start () там, где запускается таймер линии. Первое значение получилось 957. Если это в миллисекундах, то надо поделить на 1000, то получается 0.957, а должно быть 0.05. Почему так?
sidsukana
Скорей всего прорисовка происходит в отдельном потоке, а значит Line.drawLine() отработает без задержек.
zuze
Цитата(sidsukana @ 30.1.2013, 10:51) *
Скорей всего прорисовка происходит в отдельном потоке, а значит Line.drawLine() отработает без задержек.


При повторном запуске первое значение 905, а второе 109, третье 312, четвёртое 375. Скорость линии не менялась. Очень странные значения выводятся?
sidsukana
Что за первое второе третье и четвертое? вам нужно только elapsed() - возвращает время в мс прошедшее после вызова start().
zuze
Цитата(sidsukana @ 30.1.2013, 11:02) *
Что за первое второе третье и четвертое? вам нужно только elapsed() - возвращает время в мс прошедшее после вызова start().


У меня вертикальная линия передвигаеться по горизонтали до тех пор пока я не останавлю. От точки до точки передвижение идёт со скоростью 50 миллисекунд или 0.05 секунд. Наверно надо обнулять таймер или делить на количество отрезков пройденной линией.

Цитата(sidsukana @ 30.1.2013, 11:02) *
возвращает время в мс прошедшее после вызова start().


А в каких единицах возвращает?

sidsukana
http://doc.qt.digia.com/qt/qtime.html#elapsed

int в миллисекундах.
zuze
Решил замерить так:

Глобально объявил

uint start;


Где запускаю таймер линии делаю

start = GetTickCount();


После перерисовки линии, то есть update()

if (static_cast<int>(MyRadianToGradus(phi)+0.5) == 360)
   qDebug() << GetTickCount() - start;


Начал показывать значения, но почему-то не точные, буду разбираться.
zuze
Дело в том, что у меня линия сдвигается от 0 до 720. Каждый раз идёт сдвиг на 6 градусов, только в прямоугольных координатах. Получается, полностью линия пройдёт за 120 сдвигов.
Следовательно надо в таймере (0.05*1000) / 120. Но это значение меньше 1 мс. Но на 120 сдвиге будет равна 50.

1. Может быть интервал времени каждого сдвига меньше 1 мс и из-за этого неправильные результаты показывает?
2. Если да, то что с этим делать?
sidsukana
Если ты каждый сдвиг измеряешь, а так как значение меньше 1мс и выведет 0, то само собой сумма нулей равна нулю)
zuze
Цитата(sidsukana @ 31.1.2013, 10:50) *
Если ты каждый сдвиг измеряешь, а так как значение меньше 1мс и выведет 0, то само собой сумма нулей равна нулю)


Что удивительно значение не 0, а 800 с чем то или около 800. Почему так, не могу понять?

Как я узнал функция GetTickCount() имеет очень большую погрешность 10 миллисекунд. Может использовать "QueryPerformanceCounter"? Вроде это очень точное определени.
sidsukana
В C++11 есть модуль chrono для точного измерения времени
http://stackoverflow.com/questions/1487695...esolution-timer вот примеры работ
Но это С++11 нет гарантий что ваш компилятор поддерживает его.
Алексей1153
zuze, такие точности в одном цикле не посчитаешь. Делай 1000 полных циклов сдвига, замеряй общее время, потом дели на 1000

при этом можно обойтись простым секундомером или секундной стрелкой на простых часах :)

Цитата
Как я узнал функция GetTickCount() имеет очень большую погрешность 10 миллисекунд.

а это чушь - функция возвращает счётчик тиков с начала включения системы, при чём тут какая-то погрешность ? Другое дело, что вызывать из обычного потока со слипами её получится с не очень точным периодом - порядка 10...16мс

и ещё вопрос - зачем делается это измерение ? Это важный вопрос )
zuze
Цитата(Алексей1153 @ 31.1.2013, 12:32) *
и ещё вопрос - зачем делается это измерение ? Это важный вопрос )


Это важный вопрос, так как у меня начальная скорость 0.05 секунды до 10 секунд. Всё что от 0.5 секунды я могу определить на глаз, а остальное к сожалению нет.

Глобальные переменные

LARGE_INTEGER timerFrequency, timerStart, timerStop;
int timerdelete = 0;


Где запускаю таймер линии делаю

QueryPerformanceFrequency(&timerFrequency);
QueryPerformanceCounter(&timerStart);


После перерисовки линии, то есть update()

if (static_cast<int>(MyRadianToGradus(phi)+0.5) == 360)
{
  QueryPerformanceCounter(&timerStop);
  double const t( static_cast<double>((timerStop.QuadPart - timerStart.QuadPart) / timerFrequency.QuadPart) / timerdelete);
  qDebug() << t;
  timerdelete++;
}


Я устанавливаю таймер 2 секунды и вот какие значения выводятся, после того как линия пройдёт оборот:

1
1
1
1.25
1.2
1.16667
1.28571
1.25
1.22222
1.2
1.27273
1.25
1.23077
1.28571
1.26667
1.25
1.29412
1.27778
1.26316
1.3
1.28571
1.27273
1.30435
1.29167
1.28
1.26923
1.2963
1.28571
1.27586
1.3
1.29032
1.28125
1.30303
1.29412
1.28571
1.30556
1.2973
1.28947
1.30769
1.3
1.29268
1.28571
1.30233
1.29545
1.28889
1.30435
1.29787
1.29167
1.30612
1.3
1.29412
1.30769
1.30189
1.2963
1.29091
1.30357
1.29825
1.2931
1.30508
1.3
1.29508
1.30645
1.30159
1.29688
1.30769
1.30303
1.29851
1.30882
1.30435
1.3
1.29577
1.30556
1.30137
1.2973
1.30667
1.30263
1.2987
1.30769
1.3038
1.3
1.30864
1.30488
1.3012
1.30952
1.30588
1.30233
1.29885
1.30682
1.30337
1.3
1.30769
1.30435
1.30108
1.30851
1.30526
1.30208
1.30928
1.30612
1.30303
1.3
1.30693
1.30392
1.30097
1.30769
1.30476
1.30189
1.30841
1.30556
1.30275
1.30909
1.30631
1.30357
1.30088
1.30702
1.30435
1.30172
1.30769
1.30508
1.30252
1.30833
1.30579
1.30328
1.30894
1.30645
1.304
1.30952
1.30709
1.30469
1.30233
1.30769
1.30534
1.30303
1.30827
1.30597
1.3037
1.30882
1.30657
1.30435
1.30935
1.30714
1.30496
1.30986
1.30769
1.30556
1.31034



Такие значения возможны при задании таймера 2 секунды, если да то почему?
Алексей1153
1) повторю попрос - зачем делается такое точное задание скорости и зачем скорость измеРяется ?

От первого ответа зависит то, как будет задаваться эта скорость.

2) Что там за абстрактная такая линия - я до сих пор не знаю )) Что она у тебя делает - тоже.

3) Если так важна точная скорость, то перерисовка не должна иметь приоритет, а должна случаться когда это возможно.

4) с учётом пункта 3 - лог вывода времени, полученный в процедуре отрисовки, не имеет смысла
zuze
Цитата(Алексей1153 @ 31.1.2013, 13:34) *
1) повторю попрос - зачем делается такое точное задание скорости и зачем скорость измеРяется ?


Точное задание скорости требуетья, так как погрешность в ней не допустима.
Скорость измеряеться для того что бы наглядно убедится, что передвижение линии меняеться с нужной скоростью.

Цитата(Алексей1153 @ 31.1.2013, 13:34) *
2) Что там за абстрактная такая линия - я до сих пор не знаю )) Что она у тебя делает - тоже.


Это вертикальная линия передвигающаяся с 0 до 720. Этот промежутук со сдвигом 6 градусов по прямоугольной системой должно пройти за указанное время, которое я могу установить. Время от 0.05 до 10 секунд.
После прохождения 720 линия возвращается в 0.


Цитата(Алексей1153 @ 31.1.2013, 13:34) *
3) Если так важна точная скорость, то перерисовка не должна иметь приоритет, а должна случаться когда это возможно.


У меня рисуеться каждый раз, когда у проходит время 120 часть от заданной части. 120 частей, так как от нуля со сдвигом 6 градусов в прямоуголных координатах будет проходить 120 раз.
Алексей1153
1) сделай класс-поток, который будет работать таймером. в run там всего лишь будет цикл с вызовом msleep(1) и инкремент мембера-переменной типа uint64_t

у класса пусть также будет метод получения текущего значения счётчика, ну и должен быть мутекс, само собой, для синхронизации инкремента и возврата. Хотя, я смотрю, ты виндовый АПИ вызываешь, так что можешь обойтись без мутекса - InterlockedIncrement . Но кроссплатформа совсем идёт лесом тогда ))

2) поток, совершающий рассчёт текущего положения : опрашивает поток-таймер и следит за приростом времени. В нормальном режиме будет прирастать по 1 . Если будет 2 и больше - это говорит о том, что программа не успевает что-то выполнять (ту же перерисовку). Но потоку-двигателю на это, в принципе, пофиг: если прирост времени 5, то он сдвинет линию сразу так, как-будто прошло 5 единиц времени.

3) основной поток - работает по событиям системы, малый приоритет. Быстренько через мутекс копирует из потока-двигателя инфу о текущем положении линии и рисует кадр после этого (в момент рисования блокировку надо уже снимать)
zuze
Сделал так:

Глобальные переменные

LARGE_INTEGER timerFrequency, timerStart, timerStop;
double timerdelete = 1.0;
double t;


Где запускаю таймер линии делаю, но перед запуска таймера линии (пробовал и после запуска таймера линии - результат такой же)

QueryPerformanceFrequency(&timerFrequency);
QueryPerformanceCounter(&timerStart);


После перерисовки линии, то есть update(). update() вызывается каждый раз когда происходит сдвиг линии на 6 градусов в прямоугольных координатах. Это время равно (заданное время в секундах * 1000) / 120.

if (static_cast<int>(MyRadianToGradus(phi)+0.5) == 360)
{
   QueryPerformanceCounter(&timerStop);
   t = timerStop.QuadPart - timerStart.QuadPart;
   t = (t / timerFrequency.QuadPart) / timerdelete;
   qDebug() << t;
   timerdelete++;
}


Я устанавливаю таймер 2 секунды и вот какие значения выводятся, после того как линия пройдёт оборот:

1.36937
1.35802
1.3624
1.35909
1.35642
1.3549
1.35738
1.35844
1.35802


Значения стали уже получше, но всё равно, мне кажется, какая-то большая слишком погрешность. В чём же ещё может быть дело или такая погрешность возможна?
Iron Bug
запусти процесс с риалтайм приоритетом.
не используй вывод там, где считаешь времена. любой вывод - это ОЧЕНЬ тормозной процесс. складывай значения в массив, а в конце программы (или в параллельном потоке с низким приоритетом) выдавай значения на экран.
ну и в дебаге может очень сильно тормозить иногда.
lanz
Насчет риалтайм приоритета - может быть не лучшее решение, интересная статья на тему:
http://blogs.msdn.com/b/oldnewthing/archiv...0/10022675.aspx

Цитата
Точное задание скорости требуетья, так как погрешность в ней не допустима.

Это не возможно, погрешность все равно будет, вопрос какая она будет и будет ли накапливатся.

Хорошо было бы, если бы вы обрисовали задачу поподробнее - почему погрешность недопустима.
Возможно два варианта:
1. Линия должна делать оборот ровно за какое то время.
Для этого можно использовать QTime запущенный в начале программы, вариант предложенный Алексей1153(единственное что мне не нравится, это использование sleep, поскольку поток проснется через время несколько большее заданного, будет накапливатся погрешность) или сделать свою оберку хоть для GetTickCount хоть для QueryPerformanceCounter (тут надо быть осторожным, например http://www.synbion.ru/queryperformancecoun...ogo-dejstviya/).
В paintEvent'e мы тогда сможем получить точное время текущего кадра и вычислить необходимое смещение (такой прием используется везде при анимации, смотрите любой туториал)
В этом случае будут скачки, торможения, но если мы зададим 1000 оборотов, то будем уверены что они совершатся за (1000 * 0.05) +- delta.
2. Наблюдаемая скорость должна быть постоянной (без скачков).
В этом случае запрещается пропускать кадры (опаздывать с отрисовкой). Этот вариант на самом деле я даже не могу придумать для чего и нужен.

В любом случае более подробное описание задачи всем поможет .)
Алексей1153
lanz, sleep в Qt-шном потоке - это не винапишный sleep , он (кутешный слип) отрабатывает указанное время (думаю, там используется нативный WaitForSingleObject).

ошибка если и будет накапливаться , то очень медленно

мне в Qt атомной точности не требовалось, но - поставить эксперименты да выяснить )
lanz
Цитата(Алексей1153 @ 1.2.2013, 10:09) *
lanz, sleep в Qt-шном потоке - это не винапишный sleep , он (кутешный слип) отрабатывает указанное время (думаю, там используется нативный WaitForSingleObject).


void QThread::sleep(unsigned long secs)
{
    ::Sleep(secs * 1000);
}
void QThread::msleep(unsigned long msecs)
{
    ::Sleep(msecs);
}
void QThread::usleep(unsigned long usecs)
{
    ::Sleep((usecs / 1000) + 1);
}

:lol:

Цитата
мне в Qt атомной точности не требовалось, но - поставить эксперименты да выяснить )

Родина приказала - сделаем)
У меня за 2 минуты набежало 85 мс.
На самом деле точность не получится никогда, лучшее что можно сделать - чтобы погрешность не накапливалась.
Алексей1153
Цитата(lanz @ 1.2.2013, 12:59) *
У меня за 2 минуты набежало 85 мс.


и не удивительно )

void ClockThread::run () {
for (int i = 0; i < 120000; ++i){
this->msleep (1);
emit tick (); <<<<<<<<<<<<<<<<<<<<<
QApplication::processEvents ();<<<<<<<<<<<<<<<<<<<<<
};
};

Цитата(lanz @ 1.2.2013, 12:59) *
На самом деле точность не получится никогда, лучшее что можно сделать - чтобы погрешность не накапливалась.


на самом деле всё зависит от задачи, где-то пофиг и на набегающую погрешность
lanz
for (int i = 0; i < 120000; ++i){
    this->msleep (1);
    InterlockedIncrement (&this->counter);
};

Смещение будет меньше (около 10мс) но все равно будет. Хороший велосипед - все равно велосипед .)

Цитата
на самом деле всё зависит от задачи, где-то пофиг и на набегающую погрешность

Вот под этим подпишусь.
zuze
Я проверил так, если запускаю таймер на 5 секунд, то отображаеться. 5,7 секунды. Но когда я запускаю таймер 5 секунд и параллельно запускаю программу-секундомер "Oiynsoft StopWatch v4.0", то всё правильно показывается 5 секунд и там и там.

У меня есть идея, что дело в том, что я изменяю значение в методе start таймера, то есть

timer->start((ui->doubleSpinBox->value()*1000)/60);


А он должен быть вроде неизменяемым.

Может надо делать так:

timer->start(10);


А где меняется сдвиг линии, надо делать так:

phi += (360*10) / (ui->doubleSpinBox->value() * 1000);


1. 360 - это градусы
2. 10 - это время таймера в миллисекундах
3. ui->doubleSpinBox->value() * 1000 - время оборота линии в миллисекундах

Конечно это phi надо ещё перевести в экранные координату, но на общую логику это не влияет.

Правильно ли я рассуждаю или я вообще не в ту сторону пошёл?
Алексей1153
возможно, связано с вызовом той программой функции timeBeginPeriod

http://msdn.microsoft.com/en-us/library/wi...4(v=vs.85).aspx
zuze
Код для расчёта времени.

Глобальные переменные

LARGE_INTEGER timerFrequency, timerStart, timerStop;
double t;


После запуска таймера линии

QueryPerformanceFrequency(&timerFrequency);
QueryPerformanceCounter(&timerStart);


После update() который вызываеться по таймеру

if (static_cast<int>((((phi)/720.0)*360)+0.5) == 360)
{
        QueryPerformanceCounter(&timerStop);
        t = timerStop.QuadPart - timerStart.QuadPart;
        t = t / (double)timerFrequency.QuadPart;
        qDebug() << t;
}


Может я ещё не в тех местах вызываю чётчик или не так описал его?
Алексей1153
я перестал тебя понимать )))

Попробуй вызвать в своей программе (в начале работы)

timeBeginPeriod(1)
повлияет ли это на точность ?

и ещё timeBeginPeriod(2) тоже попробуй. По хорошему, надо, конечно, так


    TIMECAPS tc;
    timeGetDevCaps(&tc,sizeof(tc));
    uint32_t periodSet=max(1,tc.wPeriodMin);
    timeBeginPeriod(periodSet);

Iron Bug
Цитата(lanz @ 1.2.2013, 11:46) *
Насчет риалтайм приоритета - может быть не лучшее решение

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


вообще, если по-правильному проектировать, то слипы тут нужно делать не относительные, а абсолютные. не знаю, умеет ли это Qt. смысл в том, чтобы спать не определённое время, а до заранее указанного момента в абсолютном времени. и при этом каждый раз считать погрешность и вычислять среднее значение погрешности по последним замеренным результатам, и это среднее значение вычитать из следующего интервала. как-то так. может, можно и относительные слипы юзать, но вот в бусте, например, они неточные. по какой причине - я хз. просто в большинстве случаев под вендой так получалось, что относительные слипы не давали нужной скорости выхода потока из спячки. насчёт Qt, если она поддерживает несколько видов слипа, это нужно проверять отдельно.
я несколько раз реализовывала подобные вещи, но с помощью boost (однако, под вендой всё равно приходилось корячиться через QueryPerformanceConter в качестве счётчика).
естественно, это только поток вычислений. прорисовка строго отдельно и с более низким приоритетом. на больших скоростях прорисовка каждой линии тут, скорее всего, не получится. получится некое усреднение. то есть, важно знать, где рисовать в данный момент. а уж плюс-минус на отображение можно минимизировать, если юзать OpenGL, например, и буферы.

и, кстати, имейте в виду, что QueryPerformanceCounter имеет некоторые косяки на некоторых чипсетах. в общем, там частота может плавать, а он считает её константой. и получается, что тайминги тоже плавают. как-то так. таких платформ немного, но эта фигня есть.
плюс если добрый юзер в момент работы вашей софтины сменит время - надо ловить WM_TIMECHANGE и реинициализировать таймер.
просто я не эти грабли уже не один раз наступала.
lanz
Настоящий риалтайм только в RTOS.
Да тут он и не нужен.
Можно конечно сделать риалтаймовый процесс, выверить его чтобы он спал нужное время и уступал другим, но зачем? Это все и так делает TaskManager.
Делать вычисления в риалтайме вообще непонятно зачем, весь интерфейс залипнет (а если делать перерывы на разбор сообщений, то опять получается TaskManager).

Iron Bug, просто из любопытства - какие задачи стояли перед вами, что пришлось использовать риалтайм приоритет?
Iron Bug
Цитата(lanz @ 12.2.2013, 16:37) *
Iron Bug, просто из любопытства - какие задачи стояли перед вами, что пришлось использовать риалтайм приоритет?

моя обычная работа: разработка ПО для банковской техники :)
ПО у меня всё хардварно-зависимое, либо дрова.

Цитата(lanz @ 12.2.2013, 16:37) *
Это все и так делает TaskManager.

да вот без риалтайма не делает нифига. без риалтайма под вендой всё плавает вкривь и вкось и повторяемости по временам добиться в принципе невозможно. даже для задач, которые вообще не требуют вычислений.
в данном случае "вычисления"- это всего лишь эмуляция нормального микросекундного таймера. а в таймере точность нужна.
zuze
У меня получается так, что скорость по умолчанию таймера линии, меньше одной миллисекунды. Дело в том, что там стоит полный оборот в секундах, а именно 0,05 секунды. То есть это время полного оборота линии. Я умножаю на 1000, так как start() задаётся в миллисекундах. А затем я делю на 60. Что бы скорость была сдвига, я каждый раз на 12 сдвигаю, до 720 и это получается 60 раз. Но выражение в start()-е (0,05 * 1000) / 60 меньше одной миллисекунды, оно примерно равно 0,83333333333333333333333333333333. Может для таких мелких значений надо что-что дополнительное в Qt прописывать для таймера или вообще он с такими величинами не работает?
Алексей1153
zuze, тебе нужно обороты измерять в тактах, а не наоборот. Тогда потери точности здесь не будет
zuze
Цитата(Алексей1153 @ 13.2.2013, 10:56) *
тебе нужно обороты измерять в тактах, а не наоборот. Тогда потери точности здесь не будет


Как я понял я здесь измеряю каждое передвижение линии, я думал при старте надо задать начальное время, а когда равно будет 720, то вычислять пройденное, а оказываеться не так нужно.
Подскажите пожалуйста, как нужно в таком случае поступить?
Алексей1153
так что мешает запомнить время, которое было в момент старта ? И учитывать его как отправную точку в расчётах
zuze
Цитата(Алексей1153 @ 13.2.2013, 11:03) *
так что мешает запомнить время, которое было в момент старта ? И учитывать его как отправную точку в расчётах


Я так и делаю.

После start()

QueryPerformanceFrequency(&timerFrequency);
QueryPerformanceCounter(&timerStart);


После update() который вызываеться по таймеру

// Как пройдёт линия доконца выведится время
if (static_cast<int>((((phi)/720.0)*360)+0.5) == 360)
{
        QueryPerformanceCounter(&timerStop);
        t = timerStop.QuadPart - timerStart.QuadPart;
        t = t / (double)timerFrequency.QuadPart;
        qDebug() << t;
}


Вроде всё верно, но вместо 0,05 секунды выводится 0,5 секунд. Что же не так?




Алексей1153
выведи все цифры в консоль, так проще увидеть, где что не так

        QueryPerformanceCounter(&timerStop);

        qDebug() <<"timerStop.QuadPart="<<timerStop.QuadPart;
        qDebug() <<"timerStart.QuadPart="<<timerStart.QuadPart;

        t = timerStop.QuadPart - timerStart.QuadPart;
        qDebug() <<"diff="<< t;

        qDebug() <<"timerFrequency.QuadPart="<<timerFrequency.QuadPart;
        t = t / (double)timerFrequency.QuadPart;
        qDebug() <<"t="<< t;
zuze
Цитата(Алексей1153 @ 13.2.2013, 11:20) *
выведи все цифры в консоль, так проще увидеть, где что не так


Сделал.

Получаеться так:

timerStop.QuadPart= 39669101482 
timerStart.QuadPart= 39667533374
diff= 1.56811e+06
timerFrequency.QuadPart= 2825625
t= 0.55496


А таймер задаётся 0.05, то есть такое значение должно t выводить.
Алексей1153
Цитата(zuze @ 13.2.2013, 14:25) *
А таймер задаётся 0.05,

а где он задаётся, что-то я не уловил
Iron Bug
Цитата(zuze @ 13.2.2013, 14:15) *
Что же не так?

qDebug() << t;
я уже писала, что любой вывод (а тем более такой тормозной, как дебажный вывод!) может сожрать 90% твоей скорости.
убери этот ужас, пиши в массив, а в конце программы этот массив распечатаешь на экран.
lanz
Мне кажется тут подход к задаче не совсем верный я бы сделал так:
1. Завел бы таймер (неважно какой, хоть QTimer, хоть обертка для QueryPerformanceCounter, хоть http://msdn.microsoft.com/ru-ru/library/wi...(v=vs.85).aspx)
2. Запустил бы его в начале.
3. Поставил бы QTimer на обновления допустим на 30 fps (1000/30).
4. В методе update я бы смотрел ДЕЙСТВИТЕЛЬНО прошедшее время (по таймеру из пт. 1)
5. Рисовал бы анимацию, соответствующую действительному времени. Т.е. умножал бы угловую скорость на время, получал бы текущее значение phi.
zuze
Цитата(Алексей1153 @ 13.2.2013, 11:45) *
а где он задаётся, что-то я не уловил


Прошу прощения стожировался. Сейчас освободился.

Я Запускаю таймер при нажатии на radioButton, таким образом:

ui->doubleSpinBox->setValue(ui->doubleSpinBox->value());
timer->start((ui->doubleSpinBox->value()*1000)/60);


А в конструкторе прописал так:

ui->doubleSpinBox->setMinimum(0.05);    // Минимальное значение
ui->doubleSpinBox->setMaximum(10);     // Максимальное значение
ui->doubleSpinBox->setSingleStep(0.01); // Интервал изменения


Цитата(Iron Bug @ 13.2.2013, 11:53) *
qDebug() << t;
я уже писала, что любой вывод (а тем более такой тормозной, как дебажный вывод!) может сожрать 90% твоей скорости.
убери этот ужас, пиши в массив, а в конце программы этот массив распечатаешь на экран.


Если так было, то тогда со второго раза только ошибка накапливалась, а она появляеться сразуже.
Iron Bug
Цитата(zuze @ 19.2.2013, 10:43) *
Если так было, то тогда со второго раза только ошибка накапливалась, а она появляеться сразуже.

от того, чтоты наблюдаешь, тормоза в подобных вещах никуда не делись. это по определению тормозная функция, как и любой другой вывод.
и я, и lanz тебе уже пытались объяснить, что надо тайминги отдельно считать, а рисовать уже в зависимости от таймингов, в низкоприоритетном потоке. графика, как разновидность вывода, тоже тормозит. и, соответственно, рассчитывать на какие-то реальные интервалы в ней нельзя. поэтому делают наоборот: тайминги и расчёты координат - в реальном времени, а рисование - как придётся, по вычисленным значениям.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.