Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: xokc от Октябрь 03, 2015, 23:35



Название: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 03, 2015, 23:35
Qt 5.5, Windows 8/Server 2012.
Имею следующий код в наследнике QThread:

Код
C++ (Qt)
void Thread::step()
{
   if (!m_printed) {
       m_printed = true;
       qDebug() << "step()" << QThread::currentThreadId();
   }
}
 
void Thread::run()
{
   qDebug() << "run()" << QThread::currentThreadId();
   m_printed = false;
 
   QTimer idle;
   connect(&idle, &QTimer::timeout, this, &Thread::step);
   idle.start(1);
   QThread::run();
}
На "обычных" (i7, i5, виртуалки) компах код работает ожидаемо - сколько потоков создано, столько же и отрабатываний в step(), причем вне зависимости от количества созданных потоков n (проверял для n <= 20). На серверных же двухпроцессорных Xeon с общим количеством ядер = 40 уже начиная с 16 потоков количество вызовов step() становится на 3-4 раза меньше, чем запущено потоков. Что это может быть?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 03, 2015, 23:59
1. Почему таймер создается как локальная переменная?
2. Зачем нужен вызов QThread::run(); ?
3. Какой таймаут у таймера? Предположение - таймер разрушается раньше, чем успевает эмитировать сигнал.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 00:27
1. Почему таймер создается как локальная переменная?
Почему - нет? Зачем ему быть переменной класса или чем-то ещё?
2. Зачем нужен вызов QThread::run(); ?
Для запуска цикла обработки событий внутри потока.
3. Какой таймаут у таймера? Предположение - таймер разрушается раньше, чем успевает эмитировать сигнал.
Таймаут 1 мс. Таймер не разрушается - он существует пока выполняется QThread::run(), то есть на протяжении всего времени жизни самого Thread.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 00:32
1. Почему таймер создается как локальная переменная?
А почему нет? :)
Таймер будет жить все время работы нитки (выполнения run), а потом автоматически разрушиться.

2. Зачем нужен вызов QThread::run(); ?
Он запускает обработку очереди событий.

3. Какой таймаут у таймера?
1 мс.

Предположение - таймер разрушается раньше, чем успевает эмитировать сигнал.
Как уже писал выше, таймеры живут все время работы нитки.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 00:33
Дуплет. :)


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 00:35
количество вызовов step() становится на 3-4 раза меньше, чем запущено потоков. Что это может быть?
А нитки, в которых не сработали потоки, продолжают работать?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 00:39
Дуплет. :)
Причём, почти дословный :)
А нитки, в которых не сработали потоки, продолжают работать?
Да, работают нормально. Да и те, которые "корявые" работают тоже - другие события они обрабатывают. Только таймерные не хотят.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 00:45
Попробуйте устанавливать интервал и запускать таймер раздельно:
Код
C++ (Qt)
setInterval( 1 );
start();
 


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 00:50
Я имел в виду последнюю строку в void Thread::run() . Там у вас QThread::run () что запускает? Просто всего кода не видно.
Hyperthreading активен, кстати?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 00:51
Я имел в виду последнюю строку в void Thread::run() . Там у вас QThread::run () что запускает?
Он запускает QThread::exec().


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 00:56
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/

Посмотрите Usage 1-2 , кажется, там похожая проблема решается.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 00:57
Попробуйте устанавливать интервал и запускать таймер раздельно:
Ожидаемо не помогло :(


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 00:59
Я имел в виду последнюю строку в void Thread::run() . Там у вас QThread::run () что запускает?
Он запускает QThread::exec().

В чем смысл? По хорошему надо бы переопределить run () и стартовать через exec (), а не наоборот.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 01:01
В чем смысл? По хорошему надо бы переопределить run () и стартовать через exec (), а не наоборот.
Нитка стартует через start, exec запускает eventloop.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 01:03
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
Посмотрите Usage 1-2 , кажется, там похожая проблема решается.
Нет, там решается другая проблема, связанная с тем, что там события таймера отрабатывают в основном потоке, а не в пользовательском. У меня этой проблемы нет.

В чем смысл? По хорошему надо бы переопределить run () и стартовать через exec (), а не наоборот.
Не заморачивайся. Можно заменить QThread::run() на exec() ничего не изменится, суть проблемы не в этом:
Код
C++ (Qt)
void QThread::run()
{
   (void) exec();
}


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 01:03
Ожидаемо не помогло :(
А увеличивать таймаут пробовали, для проверки?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 01:06
Пробовал. start(10) почти работает - периодически "залипает" одна из ниток, start(100) работает гарантированно. Но меня такой интервал не устраивает.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 01:10
Пробовал. start(10) почти работает - периодически "залипает" одна из ниток, start(100) работает гарантированно. Но меня такой интервал не устраивает.
Я так понимаю, вы хотите вызывать step сразу после запуска eventloop.
Попробуйте вместо таймера использовать QMetaObject::invokeMethod c Qt::QueueConnect.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 01:12
Мне, в целом, нужно максимально часто выполнять определенный код в тот момент когда очередь событий потока пуста. Собственно, исходил из этого посыла в документации:
To make your application perform idle processing (i.e. executing a special function whenever there are no pending events), use a QTimer with 0 timeout.
start(0) для меня чрезмерен - комп начинает "пожирать" самого себя. Может есть другие способы, особенно учитывая следующее предложение оттуда же?
More sophisticated idle processing schemes can be achieved using processEvents().


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 01:14
Вот invokeMethod для этого хорошо подходит.
В методе step просто добавляйте вызов его же самого через invokeMethod+QueueConnection и таймер не понадобиться.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 01:18
step() должен вызываться всякий раз когда нитке больше "нечего делать". В приведенном примере его полезная нагрузка опущена. Пробовал заменить QTimer на timerEvent - результат ровно тот же. С invokeMethod попробую.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 01:26
Вроде бы с invoke, на первый взгляд, заработало. Old, спасибо большое. Завтра на свежую голову проверю тщательнее. Но, в любом случае, поведение, на мой взгляд, странное. Особенно с учётом того, что этот таймерный нюанс проявляется только в мультипроцессорных конфигурациях.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 10:03
Неясно в какой нитке выполняется QThread::step. Если в главной, то все вполне объяснимо - события таймера игнорируются если в данный момент выполняется обработка предыдущего


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 10:06
Неясно в какой нитке выполняется QThread::step.
Тут остается только сожалеть.  ::)


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 10:42
Неясно в какой нитке выполняется QThread::step.
В своей собственной - в той же, которая "run()", именно для проверки этого факта выводился currentThreadId

события таймера игнорируются если в данный момент выполняется обработка предыдущего
Эта версия теоретически имеет право на жизнь, но почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 10:43
step() должен вызываться всякий раз когда нитке больше "нечего делать". В приведенном примере его полезная нагрузка опущена. Пробовал заменить QTimer на timerEvent - результат ровно тот же. С invokeMethod попробую.
Вот сейчас подумалось. Для такого поведения, возможно удобней будет в ните запустить step как основное задание, а в перерывах обрабатывать накопившиеся события.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 10:59
Эта версия теоретически имеет право на жизнь, но почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?
Наверное и теоретически не имеет. Ну хорошо, допустим один раз был занят, пропустили. Но ведь придут следующие события того же таймера - кто-то да пробьется

Тогда варианты почему это происходит:

1) Нитка загружена постоянно т.е. в ее EventLoop все время есть события - а события таймера помещаются в  EventLoop только если там никого нет. Это можно проверить отключив нагрузку

2)  EventLoop еще не запущен когда таймаут истек. Ну опять-таки неясно, ведь будут еще события таймера.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 11:16
а события таймера помещаются в  EventLoop только если там никого нет. Это можно проверить отключив нагрузку
Используется DirectConnection, слоты вызываются напрямую, никаких событий таймера в очередь не кладется.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 11:27
Вот сейчас подумалось. Для такого поведения, возможно удобней будет в ните запустить step как основное задание, а в перерывах обрабатывать накопившиеся события.
Меня самого эта корявость архитектуры несколько гложет. Суть в том, что Thread - это пул воркеров и полезный код нагрузки выглядит примерно так:
Код
C++ (Qt)
void Thread::step()
{
   for (bool flag = true; flag;) {
       flag = false;
       for (Worker *worker : m_workers) {
           if (worker->isStepReady()) {
               worker->step();
               yieldCurrentThread();
               flag = true;
           };
       }
   }
}
 
Особенность воркеров такова, что у них потребность в работе возникает в среднем 10 раз в секунду, а продолжительность выполнения одного шага воркера достаточно мала, так что забивать комп бесконечной проверкой "не созрел ли кто для работы" тоже не хочется. С другой стороны, при достаточно большом количестве воркеров (до 1024) текущая схема тоже не выглядит идеальной. Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить? Снова таймер?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 11:31
1) Нитка загружена постоянно т.е. в ее EventLoop все время есть события - а события таймера помещаются в  EventLoop только если там никого нет.
Проверял без нагрузки - разницы нет.
И опять таки:
почему эффект не проявляется на "бытовых" ПК, а только на "серверных"?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Bepec от Октябрь 04, 2015, 11:52
Вариант отличия ПО сервера и десктопа вами рассматривается?
Вполне возможно, что какой нить хитрый механизм оптимизации имеет место быть.
Как то ограничение на количество одновременных потоков для приложения и выделяемых мощностей.

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

Ну или ещё вариант на мутексах сделать. Никакие таймеры не нужны будут.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 12:10
Вариант отличия ПО сервера и десктопа вами рассматривается?
Проверял на виртуалке Windows Server в десктопе - все работает как надо

Не иметь сотню созданных и занимающихся фигней потоков, а иметь менеджера, разруливающего количество потоков и их запуск?
Где я тут писал про сотню страдающих фигней потоков? Мои потоки (их ровно половина от имеющихся вычислительных ядер) и играют роль того самого менеджера. "Фигней страдают" воркеры - так на то они и воркеры, чтобы фигней страдать.

Ну или ещё вариант на мутексах сделать. Никакие таймеры не нужны будут.
На каких мьютексах? У меня нет общего ресурса, который нужно защищать мьютексами!


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 12:14
Используется DirectConnection, слоты вызываются напрямую, никаких событий таймера в очередь не кладется.
Напрямую "от кого"? События таймера приходят от OC, не крутим EventLoop - нет и этих событий

Особенность воркеров такова, что у них потребность в работе возникает в среднем 10 раз в секунду, а продолжительность выполнения одного шага воркера достаточно мала, так что забивать комп бесконечной проверкой "не созрел ли кто для работы" тоже не хочется. С другой стороны, при достаточно большом количестве воркеров (до 1024) текущая схема тоже не выглядит идеальной. Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить? Снова таймер?
Ну если 10 раз в секунду, то чем не устраивает избитая схема QWaitCondition::wait и wakeOne?

Edit: впечатление что таймер здесь - явно "не то"


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 12:14
И все таки... что там с гипертридингом?
Иногда бывают с ним проблемы, не раз замечено.... и именно ка ксеонах.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Bepec от Октябрь 04, 2015, 12:18
Мутексом можно блочить ресурс, а можно использовать его в качестве контролирующего элемента. Тот же QWaitCondition на этом работает, вроде.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 12:23
Напрямую "от кого"? События таймера приходят от OC, не крутим EventLoop - нет и этих событий
Не от какой ОС ничего не приходит.
Прошел или нет заданный интервал времени определяется в eventloop, и если прошло активируется слот.
А если объект слота получателя находиться в том же потоке, то это сводится к прямому колу.

В общем виде цикл обработки событий обрабатывает таймеры, опрашивает внешние события и обрабатывает сами события из очереди.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 12:27
Ну если 10 раз в секунду, то чем не устраивает избитая схема QWaitCondition::wait и wakeOne?
Кто wakeOne вызывать будет и по какому поводу?
Можно было бы просто ориентироваться на ближайший из просыпающихся воркеров и будить нитку по соответствующему таймауту в QWaitCondition::wait. Но при большом количестве воркеров не будет ли у меня система только и заниматься тем, что засыпать и просыпаться?

Edit: впечатление что таймер здесь - явно "не то"
Таймер был взят как документированное средство занять систему в период её бездействия. О том, что тоже думаю, что это не совсем "то", я уже писал.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 12:28
Но кто его будет будить? Снова таймер?
Никаких таймеров, это страшно. :)
Используйте очередь заданий с условной переменной QWaitCondition, и все будет работать как часы.
На форуме есть несколько тем, где я приводил код таких очередей. Не найдете, пишите наберу еще раз, там пара десятков строк.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 12:29
Кто wakeOne вызывать будет и по какому поводу?
Тот кто будет новую работу добавлять для воркеров.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 12:38
Новая работа им добавляется ими же :) по результатам выполнения предыдущей. Только они сами знают через какое время им нужно снова начать работать. Но ведь их нитка спит, кто же их разбудит?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 12:52
Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить?
Вот это место "осветите" - как (или откуда) появляется собственно "задание"


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 13:01
Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить?
Вот это место "осветите" - как (или откуда) появляется собственно "задание"
Каждый из воркеров знает через какое время ему стоило бы сделать свою очередную порцию работы. Соответственно, нитка могла бы пробежаться по воркерам, узнать какой из них должен начать работу первым и когда именно это должно произойти, а до того момента заснуть.
Если бы не необходимость ещё и обрабатывать события в этой самой нитке.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 13:24
Подобные вещи я делаю так. Каждый воркер имеет свой внутренний таймер, запущенный с заданным интервалом. При срабатывании - делаем работу.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 13:27
Хм. Что-то с таймерами мне больше не хочется иметь дела.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 13:28
Хм. Что-то с таймерами мне больше не хочется иметь дела.
А как без них время засекать? Крутить свой цикл с проверкой сколько крутим - будет еще хуже. :)
Тем более там у вас интервалы будут в секундах.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 13:49
Правильнее было бы потоку спать до момента появления необходимости работать ближайшему воркеру. Но кто его будет будить?
Вот это место "осветите" - как (или откуда) появляется собственно "задание"
Каждый из воркеров знает через какое время ему стоило бы сделать свою очередную порцию работы. Соответственно, нитка могла бы пробежаться по воркерам, узнать какой из них должен начать работу первым и когда именно это должно произойти, а до того момента заснуть.
Если бы не необходимость ещё и обрабатывать события в этой самой нитке.

Хм.. а чем не устраивает вариант, после того как воркер отрабатывает, отправлять его в слип на 10мс, к примеру? Проснулся - сделал работу - уснул.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 13:55
Хм.. а чем не устраивает вариант, после того как воркер отрабатывает, отправлять его в слип на 10мс, к примеру? Проснулся - сделал работу - уснул.
Для маленких интервалов (< 1 сек) - еще ничего, а для больших начинаются неприятности при завершении работы нитки. Вы сказали останавливайся, а остановиться он реально после того как закончится sleep, если это несколько секунд - уже заметно.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 14:00
Хм.. а чем не устраивает вариант, после того как воркер отрабатывает, отправлять его в слип на 10мс, к примеру? Проснулся - сделал работу - уснул.
Для маленких интервалов (< 1 сек) - еще ничего, а для больших начинаются неприятности при завершении работы нитки. Вы сказали останавливайся, а остановиться он реально после того как закончится sleep, если это несколько секунд - уже заметно.

Это понятно, но разве это не то, что хочет автор? Чтобы воркеры спали определенное время после завершения?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 14:04
Каждый из воркеров знает через какое время ему стоило бы сделать свою очередную порцию работы. Соответственно, нитка могла бы пробежаться по воркерам, узнать какой из них должен начать работу первым и когда именно это должно произойти, а до того момента заснуть.
Если бы не необходимость ещё и обрабатывать события в этой самой нитке.
А если так: завести еще "нитку 2"

1) нитка с воркрами делает ту самую пробежку и посылает "сигнал2" нитке 2
2) получив "сигнал2" нитка 2 спит заданное время если время ни одного из воркеров еще не пришло -  иначе сразу посылает "сигнал1" нитке с воркерами
3) получив "сигнал1" нитка с воркерами обслуживает готовых и возвращается к пункту 1


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 14:07
Это понятно, но разве это не то, что хочет автор? Чтобы воркеры спали определенное время после завершения?
Хочет этого, но наверное и завершаться быстро тоже хочет.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 14:15
Это понятно, но разве это не то, что хочет автор? Чтобы воркеры спали определенное время после завершения?
Хочет этого, но наверное и завершаться быстро тоже хочет.

Ну, мы это решаем просто: воркер в run () проверяет флаг завершения и флаг наличия работы. Если сказано завершиться, умираем. Если работать, работаем. Иначе короткий сон и все повторить.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 14:17
Ну, мы это решаем просто: воркер в run () проверяет флаг завершения и флаг наличия работы. Если сказано завершиться, умираем. Если работать, работаем. Иначе короткий сон и все повторить.
Спать придется всей нитке. Во время её сна не будут приниматься события. Если воркеров будет достаточно много, оверхед на процессы засыпания/побудки не получится слишком большим?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Old от Октябрь 04, 2015, 14:17
Ну, мы это решаем просто: воркер в run () проверяет флаг завершения и флаг наличия работы. Если сказано завершиться, умираем. Если работать, работаем. Иначе короткий сон и все повторить.
Я про это говорил чуть выше, это ручная эмитация работы таймера QTimer. :)


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 14:23
А если так: завести еще "нитку 2"
1) нитка с воркрами делает ту самую пробежку и посылает "сигнал2" нитке 2
2) получив "сигнал2" нитка 2 спит заданное время если время ни одного из воркеров еще не пришло -  иначе сразу посылает "сигнал1" нитке с воркерами
3) получив "сигнал1" нитка с воркерами обслуживает готовых и возвращается к пункту 1
Хотелось бы, чтобы диспетчеризацией кто-нибудь другой занимался, типа ОС :). По предложенному:
1. Нитка 1 после 1-го пункта спит по QWaitCondition::wait?
2. Нитка 2 посылает сигнал по wakeOne?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 14:26
Ну, мы это решаем просто: воркер в run () проверяет флаг завершения и флаг наличия работы. Если сказано завершиться, умираем. Если работать, работаем. Иначе короткий сон и все повторить.
Я про это говорил чуть выше, это ручная эмитация работы таймера QTimer. :)

Да, но облегченный вариант, никаких объектов таймера и сигналов :)


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Igors от Октябрь 04, 2015, 14:45
Хотелось бы, чтобы диспетчеризацией кто-нибудь другой занимался, типа ОС :). По предложенному:
1. Нитка 1 после 1-го пункта спит по QWaitCondition::wait?
2. Нитка 2 посылает сигнал по wakeOne?
1) Нет, тупо sleep.
2) Нет, просто проснулась - шлет сигнал с QueuedConnect и опять повисает на своем EventLoop

Да, это самопальный таймер, но с той разницей что ОС не может его "задвинуть взад" как он любит делать. Если время sleep значительно - порезать, напр
Код
C++ (Qt)
while (sleepMs > 0) {
int step = qMin(sleepMs, sleepStep);
sleepMs -= step;
if (abortFlag) ...
sleep(step);
}


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: kuzulis от Октябрь 04, 2015, 15:36
1. А не пробовали менять тип таймера http://doc.qt.io/qt-5/qt.html#TimerType-enum?

2. Вероятно что в ядре серверной ОС есть какие-то различия, если в десктопной работает -  а в серверной - нет. Я не уверен что qt-цы тестят свою поделку Qt на серверных ОС (надо глянуть как-нить для интереса на список ихних CI).

А таймер вообще работает в серверной ОС, если не использовать потоки? Проверял кто-нить просто стартануть таймер и посмотреть что оно скажет? Мож баг какой?  ::)




Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 16:37
Ну, мы это решаем просто: воркер в run () проверяет флаг завершения и флаг наличия работы. Если сказано завершиться, умираем. Если работать, работаем. Иначе короткий сон и все повторить.
Спать придется всей нитке. Во время её сна не будут приниматься события. Если воркеров будет достаточно много, оверхед на процессы засыпания/побудки не получится слишком большим?

В смысле всей нитке? Если каждый воркер - это отдельная нитка, то спать и просыпаться будет только он сам.

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

У нас другая неприятность как-то была - по-разному отрабатывали треды, созданные через QThread, и треды, созданные через WinAPI, в разных осях (в 7 и 8 ), насколько я помню.

И все-таки, Hyperthreading пробовали выключить?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 16:47
В смысле всей нитке? Если каждый воркер - это отдельная нитка, то спать и просыпаться будет только он сам.
Каждый воркер - НЕ отдельная нитка. В одной нитке до 256 воркеров.

И все-таки, Hyperthreading пробовали выключить?
Не, не пробовал. Слишком жирно будет ради этого HT убирать. Да и потом, на i7 с включенным HT всё работает предсказуемо.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 16:52
1. А не пробовали менять тип таймера http://doc.qt.io/qt-5/qt.html#TimerType-enum?
Не пробовал, думаю что не поможет. Если настаиваете - попробую. Просто всё "разломал" уже: от таймеров избавился и переделал на invokeMethod, там всё работает более предсказуемо.

2. Вероятно что в ядре серверной ОС есть какие-то различия, если в десктопной работает -  а в серверной - нет. Я не уверен что qt-цы тестят свою поделку Qt на серверных ОС (надо глянуть как-нить для интереса на список ихних CI).
На Windows Server пробовал в виртуалке на десктопном железе - работает нормально.

А таймер вообще работает в серверной ОС, если не использовать потоки? Проверял кто-нить просто стартануть таймер и посмотреть что оно скажет? Мож баг какой?  ::)
"Просто" работает. Даже в моём варианте из 20 ниток 17 стартуют нормально .


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Bepec от Октябрь 04, 2015, 17:52
Вы ток не путайте "я запустил серверную ос на десктопе в виртуалке", это не равняется "работает на серверной ОС с многоядерными процессорами".

Та же ОС меняет подход в зависимости от проца, так что тут нужно брать и дебажить именно на реальном железе.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: Racheengel от Октябрь 04, 2015, 18:14
Каждый воркер - НЕ отдельная нитка. В одной нитке до 256 воркеров.

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

Не, не пробовал. Слишком жирно будет ради этого HT убирать. Да и потом, на i7 с включенным HT всё работает предсказуемо.

Ну, ради эксперимента-то можно один раз попробовать. Я лично наблюдал проблему с включенным HT на 2-процессорном ксеоне.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 18:25
Вы ток не путайте "я запустил серверную ос на десктопе в виртуалке", это не равняется "работает на серверной ОС с многоядерными процессорами".
А где это-то я утверждал подобное?


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 04, 2015, 18:28
Да, но тогда получается, что воркеры работают последовательно. В чем идея? Каждый воркер имеет отдельные данные или реализует собственную обработку, отличную от других?
Воркеры - внутри одного пула (нитки) работают последовательно и независимо друг от друга. Идея в существовании нескольких таких таких пулов, выполняемых параллельно.

Ну, ради эксперимента-то можно один раз попробовать. Я лично наблюдал проблему с включенным HT на 2-процессорном ксеоне.
Если руки дойдут - попробую.


Название: Re: Не отрабатывает QTimer::timeout()
Отправлено: xokc от Октябрь 05, 2015, 09:43
Ну, ради эксперимента-то можно один раз попробовать. Я лично наблюдал проблему с включенным HT на 2-процессорном ксеоне.
Если руки дойдут - попробую.
А, не, скорее всего не попробую. Отключать НТ в БИОСе надо, а доступа к IPMI или консоли у меня нет. Возможно, когда буду рядом с железом, эта возможность и  появится, но не факт, что к тому времени проблемный код с таймерами всё ещё будет в наличии.