Название: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 22, 2012, 10:24 Доброго времени всем.
Обращаюсь ко всем Гуру многопоточного программирования Делаю консольный патчер для возможности переноса уже установленного Qt в любую другую директорию, или просто для исправления некоторых бинарных файлов (например qdoc для Qt5-betaX) или тестовых (в перспективе). Итак, имеется некая функция, которая патчит заданный бинарный файл: Код: static void patch() Есть набор бинарных файлов (набор полных путей к файлам) для патчинга. Как планирую сделать: 1. При старте приложения набор заданных имен файлов один раз помещается в некую очередь или список. Пусть будет типа queue<string>. Доступ к очереди защищается при помощи семафора. 2. Стартую оптимальное кол-во потоков. Каждый поток пытается обратиться к очереди и изъять из нее задачу - т.е. имя файла и пропатчить его. Когда поток пропатчивает файл он обращается к очереди (или списку) за новой задачей или, если задач больше нет (очередь пуста) то поток завершается. Так вот, можно ли как-то это дело оптимизировать без использования семафора/мьютекса? Или тут без вариантов? В принципе, временем на изъятие из очереди/списка имени файла можно пренебречь, т.к. это очень быстро, поэтому семафор не должен сильно задерживать потоки. Кто что думает? :) Название: Re: Несколько потоков и одна очередь задач. Отправлено: Igors от Ноябрь 22, 2012, 11:21 Так вот, можно ли как-то это дело оптимизировать без использования семафора/мьютекса? Вариантов мореИли тут без вариантов? 1) Без всяких мутексов (lock-free) через QAtomicPointer::testAndSetAcquire 2) Использовать быстрый нативный атомарный лок (на линухе вроде pthread_spin_lock) 3) Сделать свой атомарный лок на QAtomicInt (5 мин) 4) Не морочить голову себе и людям - если там хоть какие-то файловые операции, то просто QMutex только с контейнером аккуратнее - напр использовать QDoubleLinkedList Название: Re: Несколько потоков и одна очередь задач. Отправлено: SimpleSunny от Ноябрь 22, 2012, 11:29 1. В принципе, временем на изъятие из очереди/списка имени файла можно пренебречь.
2. QAtomicInt который хранит позицию первой нерешенной задачи. Название: Re: Несколько потоков и одна очередь задач. Отправлено: Igors от Ноябрь 22, 2012, 11:38 2. QAtomicInt который хранит позицию первой нерешенной задачи. Прошу исполнить :)Название: Re: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 22, 2012, 11:43 А если я не использую Qt, а использую std:: ? :)
В принципе, нашел что-то похожее тут http://progsch.net/wordpress/?p=81 UPD: Вот, блин, это ж только для C++11, значит придется писать на Qt и тянуть зависимости :( Название: Re: Несколько потоков и одна очередь задач. Отправлено: ssoft от Ноябрь 22, 2012, 11:46 Лучше сделать как проще. А проще сделать (если самому парится с синхронизацией) через семафор, который считает количество заданий.
Очередь опустошается - семафор устанавливается в 0 и начинает блокировать потоки. Появляются задания - счетчик не 0 и потоки начинают работать. Если время парсинга много больше времени работы семафора не нужно задумываться над атомарной синхронизацией. Еще лучше посмотреть в сторону QtConcurent (если использовать Qt) и не выдумывать велосипед (мопед и др.). Название: Re: Несколько потоков и одна очередь задач. Отправлено: SimpleSunny от Ноябрь 22, 2012, 11:47 Прошу исполнить :) Если задач не сильно много и их (или указатели на них) можно держать в памяти до конца и они не меняются (как было у ТС). Код
Название: Re: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 22, 2012, 11:55 Ну, блин, эти все решения на Qt. А я не хотел привязываться к Qt для такой простой консольной программки
и тянуть длл-ки и т.п. Вопросы: 1. А если я буст поробую использовать, то сильно вырастет размер бинарика? 2. Есть ли в бусте что-то вроде boost::cout ? Или не париться с потоками, и замутить на stl, обрабатывая файлы тупо по-порядку ? ЗЫ: С бустом дела не имел. Название: Re: Несколько потоков и одна очередь задач. Отправлено: Bepec от Ноябрь 22, 2012, 12:02 Буст такой же набор библиотек как и Qt.
1. Не сильно вырастет, если не будете тянуть дофига всего из него. 2. Эммм... а стандартный cout вообще не катит, да? Название: Re: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 22, 2012, 12:04 Цитировать 2. Эммм... а стандартный cout вообще не катит, да? Просто думал, что в бусте все свое, родное, независимо от stl. :) Название: Re: Несколько потоков и одна очередь задач. Отправлено: Igors от Ноябрь 22, 2012, 13:10 Ну, блин, эти все решения на Qt. А я не хотел .. Предупреждать, блин, надо чтобы воздух не гонять. Ладно1) Возможно QAtomicInt и не потребует никаких либов - все на хедерах. 2) Если gcc то "достаточно одной таблетки", напр __sync_fetch_and_add, дальше меняете 2 строки в примере SimpleSunny Код
Название: Re: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 22, 2012, 13:16 Ок, спасибо всем.
Буду делать на stl + boost, т.к. возможно мультиплатформенное использование с разными компиляторами (которые не поддерживают C++0x). А вместо mutex/semaphore наверное использую что-то вроде atomic int. Название: Re: Несколько потоков и одна очередь задач. Отправлено: Akon от Ноябрь 22, 2012, 21:20 имхо, лок-фри для такой задачи не нужен, поскольку время обработки задания велико. В бусте тоже много примитивов синхронизации: мьютексы и т.д.
Название: Re: Несколько потоков и одна очередь задач. Отправлено: kuzulis от Ноябрь 23, 2012, 09:49 Ок. Спасибо всем. Я передумал, сделаю на чистом stl без потоков. Не стоит оно того, чтобы потоки лепить. :)
|