QtConcurrent нужен совет по использованию |
Здравствуйте, гость ( Вход | Регистрация )
QtConcurrent нужен совет по использованию |
SABROG |
27.12.2009, 19:49
Сообщение
#1
|
Профессионал Группа: Участник Сообщений: 1207 Регистрация: 8.12.2008 Из: Russia, Moscow Пользователь №: 446 Спасибо сказали: 229 раз(а) Репутация: 34 |
Есть код брутфорса, который делает 4294967295 (int32) операций. По диспетчеру задач вижу, что используется только одно ядро процессора. Поэтому решил посмотреть на возможности класса QtConcurrent. В принципе задача следующая, распределить нагрузку на все ядра. 4294967295 / QThread::idealThreadCount(). Если брать конкретно ситуацию с двумя ядрами, то одно ядро должно перебирать (4294967295 / 2 = 2147483647,5) диапозон 0-2147483647, второе 2147483647-4294967295. Если один из потоков находит нужную последовательность, то я хочу иметь возможность вернуть результат и прервать все остальные потоки (сколько бы ядер не было). Также я планирую выводить QProgressDialog и если пользователь жмет "Cancel", то завершать все вычисления. Тут я планирую использовать QFutureWatcher::cancel(), однако тут тоже не понятно. Если внутри функции будет бесконечный или очень долгий цикл, сработает ли cancel()?
Каша в голове из-за обилия методов передачи указателя на мою функции или метод класса. Для начала мне нужно передать некий список с задачами, причем в задаче должен быть не один параметр. Значит придется использовать QList<QPair <int, int> > для передачи диапозонов в метод вычисления. Методы типа QtConcurrent::run(), QtConcurrent::*Reduced(), QtConcurrent::*filtered() исключаются. Первый из-за невозможности прерывания, второй из-за того, что запускается только один поток, третий из-за удаления элементов из списка при возвращении true функцией (этот функционал мне не нужен). Значит остаются QtConcurrent::map и QtConcurrent::mapped(). Из-за скудного описания я не понимаю как они работают. Эти методы блокирующие или нет? Далее насчет прогресса. Я так понял метод типа QFutureWatcher::progressValue () может мне возвратить только 2 значения: 50% и 100%, т.к. ядра 2 и потоков тоже 2. Меня это не устраивает, мне нужен реальный ход прогресса, который бы вычислялся на основе текущих значений переменной i во всех потоках. Т.е. если один поток на стадии цикла 5 из диапозона 0-10, а второй поток на стадии выполнения 2 из диапозона 11-20, то 2+5=8 - общий ход выполнения. Таким образом мне нужен механизм для влияния на QProgressDialog. Отсюда всплывают сигналы и слоты. Значит мои потоки должны уметь испускать сигналы. Стало быть список для QtConcurrent::map должен быть какой-то такой QList<QObject *>, а раз ядра 2, то и объектов в списке будет 2. Придется завести сигнал типа step(), который подключить к QProgressDialog, таким образом шквал этих сигналов от разных потоков заставит полосочку бежать вперед. Затем нужно будет завести сигнал типа finish(), чтобы мои объекты могли останавливать ход просчета на середине, если один из потоков нашел искомую комбинацию. И эту комбинацию (результат) еще надо будет как-то вернуть обратно в основной поток. В общем всё довольно сложно, может будут какие-то идеи? --- Похоже я начал вникать потихоньку. В QtCreator'e везде используется QtConcurrent::run(), причем внутри QObject'ов, в метод передается указатель this и ссылка на метод этого класса. И мне похоже надо будет создать каркас класса унаследовав QObject и создать количество экземпляров типа Task равное количеству процессоров, после чего в итерации запустить на каждом метод типа QtConcurrent::run(). --- Разработчики QtCreator'а злыдни. Используют не документированный класс QFutureInterface<> для установки прогресса и результата потока. А простые пользователи библиотеки значит должны голову ломать... Сообщение отредактировал SABROG - 28.12.2009, 0:16 |
|
|
Текстовая версия | Сейчас: 3.1.2025, 4:13 |