Задача. Считать файлы с папки, для каждого произвести некоторые действия, и результат для каждого файла записать в базу данных, которая, будем считать, находится на другом компьютере. Необходимо увеличить производительность алгоритма с помощью распараллеливания задачи между ядрами процессора. Также стоит отметить, что при работе алгоритма происходит вызов стороннего приложения и считывание результата, через коды возврата. Но это не единственное действие, выполняемое для получения результата.
Ход моих мыслей таков. Задача разбивается на три операции:
- чтение файла
- получение результата из прочитанного
- запись результата в БД
Распараллеливанию стоит подвергнуть лишь вторую операцию, потому что первая это вывод с дисковой подсистемы, третья --- работа с сетью, а вот вторая это в основном с процессором. Причем основное время тратится именно на вторую операцию, а запись в БД и чтение файла, выполняются намного быстрее.
Значит, заведу две очереди Producer-Consumer:
- производитель --- поток, выполняющий операцию чтения файлов из папки. Потребители --- потоки, получающие результат из прочитанного
- производители --- потоки, получающие результат из прочитанного. Потребитель --- поток, записывающий результат в БД
Первый вопрос, касается числа потоков-потребителей для первой очереди. В похожем вопросе Как лучше распараллелить задачу? было рекомендовано выставлять число потоков выполняющих основную работу равным количеству ядер процессора. Но не следует ли уменьшить это число, дабы "освободить" одно ядро для потоков первой и третьей операции?
Второй вопрос о том ньюансе, что операция получения результата включает вызов стороннего приложения. Не разрушит ли он эффективность распараллеливания задачи?
SaveToDb( ReadAllLines().AsParallel().Select(x=>GetResult()).ToArray() ), если строк будет всего 200 штук? – tym32167 Dec 09 '16 at 10:57AsParallel()сам подберёт оптимальное кол-во потоков? а как скажется вызовы стороннего приложения? Возможно будет в вашем варианте реализовать сообщения пользователю о прогрессе? Не будет ли проблем с использованием оперативной памяти, т.е. как должен быть реализованReadAllLines()? – 4per Dec 10 '16 at 04:12WithDegreeOfParallelism. Как напишете код, так и скажется, я не знаю как и что вы вызываете. Аналогично и про сообщение о прогрессе - будет работать только так, как вы организуете. По поводуReadAllLines- вы писали, что там всего 200 строк, так что зависит от длины этих строк, если они небольшие - то все ок, если каждая по 50 гигов, то все плохо будет. – tym32167 Dec 10 '16 at 07:40process.Start(); process.WaitForExit(timeout);– 4per Dec 10 '16 at 11:20