Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.56/64: Рейтинг темы: голосов - 64, средняя оценка - 4.56
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347

QtConcurrent::run() многоразовый вызов, очередность получения QFuture::result()

13.10.2017, 17:55. Показов 13129. Ответов 36
Метки нет (Все метки)

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

Для решения я пробовал:
C++ (Qt)
1
2
3
QFutureSynchronizer<DataIQ> syncronizer
syncronizer.addFuture(QtConcurrent::run(this,&DecodingProcess::threadWorker,
                                                    lastDecodedBlockPos,0));
И
C++ (Qt)
1
2
3
QList<QFuture<DataIQ>> futuresList;
futuresList.append(QtConcurrent::run(this,&DecodingProcess::threadWorker,
                                                    lastDecodedBlockPos,0));
В обоих случаях, что
C++ (Qt)
1
2
            for (int i=0;i<syncronizer.futures().count();i++){
                OperationDecodeDiffSp(resultData,syncronizer.futures().at(i).result());
, что
C++ (Qt)
1
2
            for (int i=0;i<futuresList.count();i++){
                OperationDecodeDiffSp(resultData,futuresList.at(i).result());
Выдает первым не то будущее, которое было запущенно, а то, которое пришло первым! Т.е. принимаемые части могут меняться местами. В однопоточном режиме, когда запускается только один объект будущего, все работает как надо.

Вопрос, как заставить их приходить в порядке запуска?

Пробовал работать с QtConcurrent::mapped(), но проблема в том, что map требует QFuture той-же размерности, что и Sequence, а я передаю в потоки не сам массив данных, прочитанных из файла, а позицию в файле. Файл читается по мере обработки. Если же передавать массив данных - при вызове map, файл просто целиком попытается грузануться в память. Это проблема.

QtConcurrent::mappedReduced() не подходит по той причине, что декодируемые блоки могут рваться и, как результат, надо будет останавливать все это дело и начинать поиск последовательности где-то в середине блока.

QtConcurrent::run() в данном случае подходит отлично, кроме того момента, что будущие результаты возвращаются не в том порядке. Как можно решить эту проблему?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.10.2017, 17:55
Ответы с готовыми решениями:

О странностях QtConcurrent+QFuture+QFutureWatcher
Вот такой код работает: QString threadFunc() { return QString(&quot;This is result&quot;); } QFutureWatcher&lt;QString&gt; watcher; //...

Использование в qtconcurrent::run() ui->
Доброго времени, форумчане! При сабже программа вылетает. Как быть? Возможно ли из лямбды послать сигнал(как же по-нубски звучит этот...

Вызов QtConcurrent приводит к зависанию GUI
Суть проблемы: есть две кнопки, по клику запускается выполнение простой процедуры в отдельном потоке и результат записывается в текстбокс....

36
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 15:22
Студворк — интернет-сервис помощи студентам
Вы говорите сначала одно потом другое, вас фиг поймешь о чем вы.

В общем, выкиньте свой гавно-код и напишите его с нуля и с разу нормально.
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 15:28  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
Либо же, зная примерный размер доступной памяти, запускать потоки для таких кусков, которые явно уместятся в памяти, дождаться завершения всех 4 потоков, записать результаты всех 4 в файл, потом переходить к следующим кускам. Так, мне кажется, будет оптимально.
Примерно так и делается. Запускать задач можно много - Qt Concurrent заботится о том, что работает одновременно максимальное количество задач, которое может проглотить система. Есть же они начинают только в тот момент, когда прочтут файл, который уже находится в потоке. Так что ситуация, когда чтение файла внутри потоков, ест гораздо меньше памяти. Результаты складывать в дополнительный массив не могу по той-же причине - все это хочет кушать, плюс копирование - самая медленная операция. Мне же нужно минимизировать время. Но решение есть - просто проходить по всем результатам в синхронайзере пока не будет нужный блок данных с нужным свойством/признаком. Тогда его забирать и искать следующий с начала.. Походу придется делать так, раз решения по самому QFutureSynchronizer нет..

Добавлено через 2 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Вы говорите сначала одно потом другое, вас фиг поймешь о чем вы.

В общем, выкиньте свой гавно-код и напишите его с нуля и с разу нормально.
Я с самого начала говорю все то-же самое. Проблема одна. Видимо вам надо читать внимательнее.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 15:36
Цитата Сообщение от Amok Посмотреть сообщение
Я с самого начала говорю все то-же самое. Проблема одна. Видимо вам надо читать внимательнее.
Проблема одна, но говорите вы об разных вещах.
Одно дело порядок выполнения потоков, другое дело порядок фьюче в контейнере.
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 15:43  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Проблема одна, но говорите вы об разных вещах.
Одно дело порядок выполнения потоков, другое дело порядок фьюче в контейнере.
Я говорю о том, что порядок фьючей в контейнере - не тот. В самом первом посте это было написано! Я не знаю как вы читали. И документация и пример говорят о том, что должно работать по другому. Я, собственно, и пришел сюда что бы спросить причину, а не обсуждать знаю ли я как работают потоки или кто из нас двоих пишет говнокод, а кто нет. Если не знаете причину - так и напишите - я не знаю, такие вещи я не писал.

Сигналы, кстати, будут работать медленнее. А скорость выполнения у меня - на первом месте.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 15:54
Цитата Сообщение от Amok Посмотреть сообщение
Я говорю о том, что порядок фьючей в контейнере - не тот.
На что я ответил что такого не может быть, и у вас кривой код.

Добавлено через 27 секунд
Цитата Сообщение от Amok Посмотреть сообщение
Сигналы, кстати, будут работать медленнее.
Экономия на спичках.
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 16:01  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
На что я ответил что такого не может быть, и у вас кривой код.
Я очень рад. Мне это очень помогло. Код приведен. Явной ошибки там, я так понял, вы тоже найти не смогли.

Цитата Сообщение от Avazart Посмотреть сообщение
Экономия на спичках.
Эти "спички" позволили мне время обработки файла в 4 потоках сократить с 8 минут до 5. Конечно - львиная доля это копирование контейнеров, но на таком объеме даже малая экономия может дать ощутимый прирост. В юбом случае я буду пробовать разные варианты и выберу тот, который мне подойдет больше.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 16:16
Цитата Сообщение от Amok Посмотреть сообщение
вы тоже найти не смогли.
Я перестал смотреть ваш код когда увидел быдлокод с QCoreApplication:rocessEvents();
(который тоже позволяет выполнятся слотам и тоже "жгет ваши спички")

Вы его выпиливать отказались, на чем разговор закрыт.
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 16:47  [ТС]
Avazart, а схрена-ли я должен выпиливать то, что не имеет отношения к заданному вопросу? Вы уверены что правильно прочитали вопрос темы? Объясните тогда, как QCoreApplication:rocessEvents(), находящийся в другом месте, связан с вопросом темы?)

QCoreApplication:rocessEvents() можно вообще удалить и не чистить память. Но проблемы это - не решит.
0
34 / 36 / 17
Регистрация: 16.04.2017
Сообщений: 478
Записей в блоге: 4
17.10.2017, 16:52
Если вы написали код,в соответствии с доками,а он не работает, и уверены,что вашей ошибки нет-напишите разработчикам.
Оставьте заявку на bug traacker-е.
В течении недели ответят.
Если, то, что вы говорите правда,и проблема в QT- надо исправлять.
(тем более управление потоками-критичная секция)

Лично напарывался на такие проблемы.
0
17.10.2017, 16:56

Не по теме:

Да проблема не в Qt а в кривых руках, это уже выяснили.

0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 17:03  [ТС]
saqef, пожалуй. Всем спасибо за ответы!

Добавлено через 6 минут
Цитата Сообщение от Avazart Посмотреть сообщение

Не по теме:

Да проблема не в Qt а в кривых руках, это уже выяснили.

Не по теме:

У кого кривые руки мы выяснили еще когда обсуждали работу с потоками в Qt в прошлый раз. Толку в ваших намеках на "кривые руки" - нет. Это мало того, что не решение проблемы, но и к ней никакого отношения не имеет в принципе.



Кстати, если делать сигналами, то придется тоже делать вызов QCoreApplication:rocessEvents() в обработчике сигнала, если поток 3 придет раньше потока 2. Просто что бы обработчик не "повис" и дал прийти сигналу со вторым куском. Либо класть все это куда-то в другой массив, но это уже снова сильно жрет память. Я этого делать избегаю.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 17:14
https://www.cyberforum.ru/blog... g4909.html
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 17:30  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Это все я знаю. Приложение - консольное. Ни форм, ничего нет. Единственный ввод - указание источника и вывода. Никаких лишних сигналов туда не попадает. Хотя, конечно, можно было написать и EventLoop:rocessEvents(), это, и правда, было бы корректнее, даже с учетом моих особенностей. Или вообще QAbstractEventDispatcher:rocessEvents( ). Но в моем случае это проблем не вызывает. Вызывается этот обработчик, когда работа должна быть остановлена и только тогда, при отмене обработки. Это видно в коде.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 17:36
Цитата Сообщение от Amok Посмотреть сообщение
Это все я знаю.
А чего тогда припераетесь ? Выпилите нафиг processEvents() ...
Цитата Сообщение от Rius
Если в коде есть DoEvents (Qt и .Net) или ProcessMessages (Delphi/C++ Builder), значит это говнокод и его надо переписать.
Причём это не сами методы плохие, а их применение говорит о недостатке знания более правильных способов.
Цитата Сообщение от Amok Посмотреть сообщение
Но в моем случае это проблем не вызывает.
Уверены? Почему тогда работает криво ?
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
17.10.2017, 17:49  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
А чего тогда припераетесь ? Выпилите нафиг processEvents() ...



Уверены? Почему тогда работает криво ?
Еще раз. Выпиливание processEvents() НЕ приводит к исправлению работы. Это приводит только к зафигачиванию в память лишних обработанных блоков, если была грубая ошибка. Кроме того, если синхронайзер очень большой, то со временем он растет. На пару метров, но тем не менее на больших объемах это заметно. cancel() решает проблему. Если все это убрать работает так-же криво. Почему работает криво - я не знаю. Если бы я знал или это было бы написано в документации я бы не спрашивал этого тут. Но в документации написано явно не то, что получается у меня.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.10.2017, 17:52
Цитата Сообщение от Amok Посмотреть сообщение
НЕ приводит к исправлению работы.
Это само по себе ошибка.
0
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
01.11.2017, 16:16  [ТС]
Косяк был в алгоритме, QFutureSynchronizer отрабатывал как надо. Всем спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.11.2017, 16:16
Помогаю со студенческими работами здесь

Как в классе Thread реализован вызов run(), если метод run() определён в АВТОРСКОМ классе?
И, следовательно, в классе Thread ничего не известно о вызове run? То есть, ребята, мне пришла в голову мысль. Коль скоро самый...

При вызове метода не возвращается значение. (вызов a.result)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace...

Вызов Run для Excelя из C# не работает
Помогите кто может... в проге подключаю Excel и пытаюсь выполнить макрос написанный в Excelе, однако выдает ошибку 'неверное количество...

Вызов скрипта самим собой под именем другого пользователя. Run As Administrator!
Есть такой скрипт. Скрипт проверяет запущен ли он с правами админа и если нет, то запускает сам себя от имени лок.админа&quot;. За основу...

Передача json массива и вызов метода для получения результатов
нужно отправить POST запрос на url API и передать JSON объект, получить ответный объект в формате json вызовом метода «calc», подскажите...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
Диалоги с ИИ
zorxor 23.05.2026
Насколько я понимаю - Вы - Искусственный Интеллект. Это так? Да, всё верно. Я — искусственный интеллект. Я представляю собой большую языковую модель, созданную для помощи в самых разных задачах. . . .
Модель здравосохранения 14. Собираем всю модель вместе.
anaschu 22.05.2026
Модель собрана. В будущих постах на видео я покажу, как она работает. В этом посте запускаем её, проверяем результаты и разбираем что можно с ней делать дальше. Перед запуском проверяем. . .
Модель здравоохранения 13. Добавление самой системы здравоохранения.
anaschu 22.05.2026
В предыдущем посте мы настроили болезни. Теперь добавим события, которые управляют здоровьем всего коллектива, а также настроим рабочий график и расчёт финансов. В Main создаём четыре события. . . .
Модель здравоохранения 12. добавление болезней через ресурпул, как аварии
anaschu 22.05.2026
Болезни — это ключевая часть нашей модели. Нам нужно, чтобы работник периодически уходил на больничный, его задание при этом зависало, а после выздоровления работа возобновлялась. Реализуем это двумя. . .
Модель здравоохранения 11. Создаём классы Задание и Работник
anaschu 22.05.2026
В AnyLogic каждая заявка и каждый ресурс — это объект определённого класса. Нам нужно создать два класса: Задание (заявка) и Работник (ресурс). Класс Задание В дереве проекта нажимаем правой. . .
Модель здравоохранения 10. Новая модель, смотрим, как добавлять логические блоки, и что писать внутри
anaschu 22.05.2026
Открываем AnyLogic, создаём новый проект. В дереве проекта появляется класс Main — это главный агент, в котором будет жить вся наша логика. Палитра блоков Слева находится палитра. Нас интересует. . .
модель ЗдравоСохранения 9. Новая модель, разбираемся, как ее создавать
anaschu 22.05.2026
В этой серии постов мы построим модель небольшого рабочего коллектива. Сотрудники получают задания, выполняют их, иногда болеют — и мы хотим посчитать, сколько это стоит компании. Метод. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru