Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] Многопоточность


Автор: wowka19 12.6.2014, 02:01
Есть возможность и острая нужда повысить быстродействие при помощи потоков.
Программой будут пользоваться на различных машинах: 2 ядра, 4 а может и 8. Отсюда вопрос: нужно ли как-то обыгрывать этот неизвестный фактор? Т.е. нужно ли во время выполнения узнавать сколько ядер на машине и от этого плясать (кол-во потоков == кол-ву логических ядер)? или не стоит париться и жестко зашить 8 потоков (или 16 про запас)? Не будет ли проблем или просадок когда потоков будет 8, а ядер - 2?

Автор: borisbn 12.6.2014, 08:23
> нужно ли во время выполнения узнавать сколько ядер на машине и от этого плясать (кол-во потоков == кол-ву логических ядер)?
Нужно. Обязательно. Тем более, что это делается просто - http://qt-project.org/doc/qt-4.8/qthread.html#idealThreadCount

Автор: wowka19 12.6.2014, 14:50
а почему?
почему нельзя создать кучу потоков про запас? они же всеравно выполнятся.

Автор: borisbn 12.6.2014, 14:59
Переключение между потоками на одном ядре гораздо более затратная вещь, чем переключение между ядрами.
У меня как-то была программа, в которой крутилось 48 потоков (по количеству каналов обработки). "Кушала" она около 40 % процессора. Когда я перевёл её на 8 потоков (по кол-ву ядер) и в каждом последовательно (!!) обрабатывал по 6 каналов, она стала кушать около 30 %. Выигрыш в производительности - четверть. Там, правда, ещё была запись на винт (из всех потоков - в один каталог), и м.б. это тоже повлияло... хз. В общем, есть только одно средство проверить... и ты, я думаю, догадываешься какой  smile 

Автор: math64 12.6.2014, 17:50
Есть такая штука - QtConcurent. Сама определит оптимальное количество потоков и создаст их. Ей нужно будет давать  задания, а она сама распределит их по потокам.

Автор: wowka19 13.6.2014, 17:40
Не могу понять QThread. В голове каша.
Задача: фоном подгружать картинки в GUI с диска. Естественно нужен отдельный поток.
Но как это сделать хз - никогда раньше не писал многопоточный код. Примеры из доки вроде понятны, но приступаю к своей задаче и впадаю в ступор.
Буду признателен, если кто приведет кусок кода для подгрузки картинки (либо любого другого ресурса) фоном. Как потом производить передачу этого ресурса в основной поток, как сбросить работу фонового потока, если он уже не актуален и нужен другой ресурс...

Автор: math64 13.6.2014, 20:39
Нужный тебе пример включен в Qt - если, конечно, ты согласен использовать QtConcurent вместо простого QThread.

Автор: wowka19 14.6.2014, 09:04
нет. хочу разобраться с QThread, но нифига не получается.
Немного конкретизирую задачу:
Есть QGraphicsPixmapItem в главном потоке. Необходимо в другом потоке подгрузить создать QPixmap и как-то его всунуть в QGraphicsPixmapItem::setPixmap(const QPixmap&). При этом QPixmap, хранящийся в QGraphicsPixmapItem, очевидно считывается главным потоком, поэтому надо как-то заблокировать или не надо... Мне бы кусочек кода, реализующий это (не надо компилируемый).

Автор: borisbn 14.6.2014, 13:00
Тебе  нужно в наследнике потока создать сигнал типа
Код
signals:
    void pixmapReady( QPixmap p );

В главном потоке после создания потока обработки сделать connect
m_workThread = new WorkThread();
Код
connect( m_workThread
    , SIGNAL( pixmapReady( QPixmap ) )
    , m_graphicsPixmapItem
    , SLOT( setPixmap( const QPixmap & ) )
);

и дёргать сигнал в потоке обработки
Код
QPixmap p;
p.blablabla...
emit pixmapReady( p );

Автор: wowka19 16.6.2014, 18:46
... при этом (продолжая предыдущий пост borisbn) не забыть переместить объект потока в контекст этого же потока - я наконец-то разобрался с QThread. Спасибо всем кто помогал!
Но я не наследую QThread, а создаю потомка QObject - загрузчика картинок и перемещаю его в контекст созданного потока QThread ( QObject::moveToThread(QThread*) ) - так имхо логичнее и понятнее ибо Qt'шные доки (где наследуется QThread и перегружается run()) только запутывают. Это я пишу для следующих вопрошающих (авось пригодится).


Остался один вопрос:
В итоге у меня два объекта из разных потоков общаются между собой через сигналы/слоты - здесь проблем никаких, но конечно же не обошлось без общих переменных, которые запрашиваются из обоих потоков. Их две и обе переменные имеют тип BOOL. Вопрос - надо ли их защищать от одновременного обращения? или запись и чтение BOOL - так скажем, "атомарные" операции, и не могут осуществляться одновременно даже если потоки выполняются на разных физических ядрах? Добавлю, что я их (переменные) не защищал, и у меня все работает без сбоев, хотя может мне просто повезло и при других условиях (компилятор, ОСь,..) все может рухнуть?..

Автор: wowka19 21.6.2014, 13:57
up:
Цитата(wowka19 @  16.6.2014,  18:46 Найти цитируемый пост)
Остался один вопрос:
В итоге у меня два объекта из разных потоков общаются между собой через сигналы/слоты - здесь проблем никаких, но конечно же не обошлось без общих переменных, которые запрашиваются из обоих потоков. Их две и обе переменные имеют тип BOOL. Вопрос - надо ли их защищать от одновременного обращения? или запись и чтение BOOL - так скажем, "атомарные" операции, и не могут осуществляться одновременно даже если потоки выполняются на разных физических ядрах? Добавлю, что я их (переменные) не защищал, и у меня все работает без сбоев, хотя может мне просто повезло и при других условиях (компилятор, ОСь,..) все может рухнуть?.. 

... и нужно ли эти переменные объявлять как volatile?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)