Название: Одновременный запуск нескольких потоков Отправлено: SeverusSnape от Сентябрь 13, 2011, 10:54 Добрый день! Начал разбираться с потоками и возникло несколько вопросов:
Суть в следующем. Организовываю в программе поиск по файлам, по содержимому. Составляю список папок в которых необходимо вести поиск и для каждой папки из этого списка создаю поток, в котором осуществляю поиск. Все работает, все отлично, но потоки хотел бы запустить одновременно, а не по очереди. Может быть чего-то не понимаю – подскажите пожалуйста, каким образом можно это организовать. Код: void SearchWidget::searchFiles(QDir & dir) Fastersearch.cpp Код: FasterSearch::FasterSearch(QObject *parent) Название: Re: Одновременный запуск нескольких потоков Отправлено: Igors от Сентябрь 13, 2011, 12:38 В любом случае сначала надо создать массивы/контейнеры всех файлов и всех рабочих ниток. Потом можно по-всякому, проще всего каждой нитке дать часть файлов (напр индекс в массиве файлов + кол-во) и запустить.
Не балуйтесь с QThread::terminate (не ищите неприятностей, дайте нитке нормально выйти). deleteLater не годится, свяжите finished со слотом где подсчитывается число отстрелявшихся ниток, ну а там уже когда все завершились разберетесь Название: Re: Одновременный запуск нескольких потоков Отправлено: SeverusSnape от Сентябрь 13, 2011, 15:51 Спасибо за ответ! Учту. Раз представилась такая возможность, уточню еще вот что - а каким образом можно ускорить создание массива папок? Могу ли я использовать для этой цели потоки. Простите за глупые вопросы, но с потоками только начинаю знакомиться
Название: Re: Одновременный запуск нескольких потоков Отправлено: Igors от Сентябрь 13, 2011, 16:38 Спасибо за ответ! Учту. Раз представилась такая возможность, уточню еще вот что - а каким образом можно ускорить создание массива папок? Эту задачу лучше отложить - неясно удастся ли здесь что-то выиграть (может быть и наоборот). В общих чертах: есть N папок/мамок. Запускаются M ниток каждой из которых дается часть из N. Каждая находит какое-то кол-во (напр 100) новых папок. Обновляем массив N, повторяем пока не останется ни одной.Вообще не нужно слишком резво все "распоточивать" :) Это непросто (если делать хорошо) Название: Re: Одновременный запуск нескольких потоков - поиск файлов Отправлено: daimon от Январь 19, 2012, 04:22 есть чуток проще реализация
Код
Основная функция запустил один раз - пойдёт рекурсия и забъётся список нужными именами файлов Как переделать под потоки? Логично при вызове рекурсии создавать новый поток и передавать параметры для поиска в текущей папке (потоки будут работать как бы по очереди, хотя не совсем) Нужно ли лепить мютекст на список и вообще, что толком такое мютекс (вроде остановка), ведь тогда теряется суть потока (они начинают работать по очереди)? Знаю, что одновременно будет писаться разными потоками мой список, для этого есть несколько решений: 1 убрать пушанье в список, а сделать ресайз и вставлять с последнего элемента, когда список пришёл, и до конца для этого потока (проблема - частый ресайз убъет производительность), на момент ресайза заблокировать список 2 убрать пушанье на каждом шаге главного списка, а для этих целей сделать локальный список и его, по концу работы потока, вставить в главный список в конец (на момент вставки заблокировать список другим потокам) 3. как-то разрулить вставку мютексами и семафорами, я это вообще не знаю самая большая проблема, это одновременная запись в список, а вдруг двое данных попытаются влезть в одну ячейку это всё теория толком реализации по блокировке списка не знаю пока ещё в функции и нет главного списка, то есть последняя вставка и сформирует весь список Название: Re: Одновременный запуск нескольких потоков Отправлено: Fregloin от Январь 19, 2012, 10:29 Код: fastSearch->searchDir(); Лучше так: Код: connect(fastSearch,SIGNAL(foundFile(QString)),this,SLOT(addItem(QString))); Название: Re: Одновременный запуск нескольких потоков Отправлено: daimon от Январь 21, 2012, 02:20 Код
там нестыковка, что за функция для кода, после QStringList lstFiles = dir.entryList( filters , QDir::Files); и нашел недостаток - создаются потоки только под количество папок самой первой вложенности, а должно ведь - новый поток, как только найдена новая папка, неважно какая вложенность поиска (тогда и получается, что поток нужно создавать в потоке) спс Название: Re: Одновременный запуск нескольких потоков Отправлено: daimon от Январь 21, 2012, 04:44 пробовал так
Код
Проблемы: 1. нереально от самого корневого потока узнать об завершении поиска 2. лагает добавление в листвиджет итемов 3. thread->getFiles().count())+ " " + QString::number(ui.listWidget->count()) возвращают разные значение - разница на 10 элементов (загадка) 4. не могу остановить родительский поток, так как умрёт цепочка дочерних, хотя не знаю почему, они же сделаны указателями 5. если приоритет поставить высокий для потоков - падает система. а так создаётся столько потоков, сколько папок от начала поиска и они ищут сами по себе файлы (как только есть папка - новый поток). Что не так в логике, подскажите, спс Название: Re: Одновременный запуск нескольких потоков Отправлено: Странник от Январь 21, 2012, 10:17 создавать новый поток для каждой папки - моветон. папок может оказаться несколько сотен. а если в папке нет файлов, а лишь вложенные папки? так вы еще и в скорости можете проиграть. я бы пробежался рекурсивно по дереву и создал очередь файлов, а для поиска по этим файлам использовал бы QThreadPool с числом потоков что-нибудь около QThread::idealThreadCount().
Название: Re: Одновременный запуск нескольких потоков Отправлено: Авварон от Январь 21, 2012, 11:05 Вообще нет смысла делать больше чем 1 поток для поиска файлов. Это связано с тем, что проверка строки на совпадение с фильтром меньше, чем получение одной энтри от ФС. А рекурсивный обход дерева ФС не параллелится (дерево же ж). Можно выиграть, как уже упоминалось, построив рекурсивно список файлов, а потом его в несколько потоков перебирать. Это даст выигрыш для большого количества файлов, но проигрыш по памяти (хранить 50тыщ полных путей к файлам в юникоде, хм...).
Это был случай поиска по имени. Если же нам надо искать не только по имени, но и, например по дате, или по содержимому, или по миметипу (к-ый, в свою очередь, тоже лезет в содержимое файла), то тут все неоднозначно. Но ясно одно - чтение данных из файла и получение его инфы опять таки дольше, чем сравнение (дата это вообще инт64, просмотреть батарей на предмет шаблона не долго). В результате, мы можем конечно закешировать всевозможную инфо о файле, но это даст очень малый прирост по скорости. Содержимое же файлов кешировать нельзя, читать из файлов в несколько потоков тоже смысла нет (да, я знаю про говеный планировщик диска в винде и про то что ВНЕЗАПНО писать/читать на диск/сдиска в несколько потоков быстрее чем в один). Название: Re: Одновременный запуск нескольких потоков Отправлено: Igors от Январь 21, 2012, 13:46 А рекурсивный обход дерева ФС не параллелится (дерево же ж). Параллелится, хотя и не просто. А вообще Вы правы - особого выигрыша здесь не поучить, все упрется в I/O. Зато как учебная multi-thread задача это подходит прекрасно (как впрочем и весь Qt) Название: Re: Одновременный запуск нескольких потоков Отправлено: daimon от Январь 21, 2012, 14:01 Вообще нет смысла делать больше чем 1 поток для поиска файлов. Это связано с тем, что проверка строки на совпадение с фильтром меньше, чем получение одной энтри от ФС. А рекурсивный обход дерева ФС не параллелится (дерево же ж). Можно выиграть, как уже упоминалось, построив рекурсивно список файлов, а потом его в несколько потоков перебирать. Это даст выигрыш для большого количества файлов, но проигрыш по памяти (хранить 50тыщ полных путей к файлам в юникоде, хм...). проблема та состоит, чтобы составить это массив, это ж нужно обойти все те папки))) - время, времяЭто был случай поиска по имени. Если же нам надо искать не только по имени, но и, например по дате, или по содержимому, или по миметипу (к-ый, в свою очередь, тоже лезет в содержимое файла), то тут все неоднозначно. Но ясно одно - чтение данных из файла и получение его инфы опять таки дольше, чем сравнение (дата это вообще инт64, просмотреть батарей на предмет шаблона не долго). В результате, мы можем конечно закешировать всевозможную инфо о файле, но это даст очень малый прирост по скорости. Содержимое же файлов кешировать нельзя, читать из файлов в несколько потоков тоже смысла нет (да, я знаю про говеный планировщик диска в винде и про то что ВНЕЗАПНО писать/читать на диск/сдиска в несколько потоков быстрее чем в один). Название: Re: Одновременный запуск нескольких потоков Отправлено: daimon от Январь 21, 2012, 14:09 пробовал так Код
Проблемы: 1. нереально от самого корневого потока узнать об завершении поиска 2. лагает добавление в листвиджет итемов 3. thread->getFiles().count())+ " " + QString::number(ui.listWidget->count()) возвращают разные значение - разница на 10 элементов (загадка) 4. не могу остановить родительский поток, так как умрёт цепочка дочерних, хотя не знаю почему, они же сделаны указателями 5. если приоритет поставить высокий для потоков - падает система. а так создаётся столько потоков, сколько папок от начала поиска и они ищут сами по себе файлы (как только есть папка - новый поток). Что не так в логике, подскажите, спс сделал замер по времени, где-то проигрую с потоками в 2 раза по сравнению с рекурсией циклов, мда вот так параллельность Название: Re: Одновременный запуск нескольких потоков Отправлено: Igors от Январь 21, 2012, 14:58 Что не так в логике, подскажите, спс Грубо говоря Вы делаете так: получили dir, создали новую нитку и дали ей этот dir. Такое размножение ниток плохо, о чем уже не раз говорилось, и в этой теме тоже. Здесь хорошо подходит "stealing" техника (нитка у которой нет задач начинает "воровать" задачи из очереди другой). Название: Re: Одновременный запуск нескольких потоков Отправлено: daimon от Январь 21, 2012, 15:40 Что не так в логике, подскажите, спс Грубо говоря Вы делаете так: получили dir, создали новую нитку и дали ей этот dir. Такое размножение ниток плохо, о чем уже не раз говорилось, и в этой теме тоже. Здесь хорошо подходит "stealing" техника (нитка у которой нет задач начинает "воровать" задачи из очереди другой). это как понять, воровать и нитка без задач? |