Возможно, вы этого не знаете, но члены класса Parallel
— это просто (сложные) оболочки вокруг объектов Task
. Если вам интересно, класс Parallel
создает объекты Task
с помощью TaskCreationOptions.None
. Однако MaxDegreeOfParallelism
повлияет на эти объекты задачи, независимо от того, какие параметры создания будут переданы конструктору объекта задачи.
TaskCreationOptions.LongRunning
дает «подсказку» базовому TaskScheduler
, что он может работать лучше с превышением количества потоков. Переподписка хороша для потоков с высокой задержкой, например, ввода-вывода, потому что она назначит более одного потока (да, потока, а не задачи) одному ядру, так что ему всегда будет чем заняться, вместо того, чтобы ждать операция для завершения, пока поток находится в состоянии ожидания. На TaskScheduler
, который использует ThreadPool
, он будет запускать задачи LongRunning в своем собственном выделенном потоке (единственный случай, когда у вас есть поток для каждой задачи), в противном случае он будет работать нормально, с планированием и перехватом работы ( собственно, чего вы тут хотите)
MaxDegreeOfParallelism
управляет количеством одновременно выполняемых операций. Это похоже на указание максимального количества разделов, на которые будут разделены и обработаны данные. Если бы можно было указать TaskCreationOptions.LongRunning
, все, что нужно было бы сделать, это ограничить количество одновременно выполняемых задач, подобно TaskScheduler
, максимальный уровень параллелизма которого установлен на это значение, аналогично этому примеру.
Вам может понадобиться Parallel.ForEach
. Однако добавление MaxDegreeOfParallelism
, равного такому большому числу, на самом деле не гарантирует, что одновременно будет выполняться такое количество потоков, поскольку задачи по-прежнему будут контролироваться ThreadPoolTaskScheduler
. Этот планировщик будет уменьшать количество потоков, работающих одновременно, до минимально возможного количества, что, я полагаю, является самой большой разницей между двумя методами. Вы можете написать (и указать) свой собственный TaskScheduler
, который будет имитировать максимальную степень поведения параллелизма и иметь лучшее из обоих миров, но я сомневаюсь, что вы заинтересованы в этом.
Я предполагаю, что в зависимости от задержки и количества фактических запросов, которые вам нужно выполнить, использование задач будет работать лучше во многих (?) Случаях, хотя в итоге потребуется больше памяти, в то время как параллельное использование ресурсов будет более последовательным. Конечно, асинхронный ввод-вывод будет работать чудовищно лучше, чем любой из этих двух вариантов, но я понимаю, что вы не можете этого сделать, потому что используете устаревшие библиотеки. Так что, к сожалению, вы застрянете с посредственной производительностью независимо от того, какой из них вы выберете.
Реальным решением было бы найти способ реализовать асинхронный ввод-вывод; так как я не знаю ситуацию, я не думаю, что могу быть более полезным, чем это. Ваша программа (чтение, поток) продолжит выполнение, а ядро будет ждать завершения операции ввода-вывода (это также известно как использование портов завершения ввода-вывода). Поскольку поток не находится в состоянии ожидания, среда выполнения может выполнять больше работы с меньшим количеством потоков, что обычно приводит к оптимальному соотношению между количеством ядер и количеством потоков. Добавление большего количества потоков, как бы мне этого ни хотелось, не означает повышения производительности (на самом деле, это часто может повредить производительности из-за таких вещей, как переключение контекста).
Однако весь этот ответ бесполезен для определения окончательного ответа на ваш вопрос, хотя я надеюсь, что он даст вам необходимое направление. Вы не узнаете, что работает лучше, пока не профилируете это. Если вы не попробуете их оба (я должен уточнить, что я имею в виду задачу без опции LongRunning, позволяющую планировщику обрабатывать переключение потоков) и не профилировать их, чтобы определить, что лучше всего подходит для вашего конкретного варианта использования, ты недооцениваешь себя.
person
Christopher Currens
schedule
21.05.2012
TaskCreationOptions.LongRunning
планировщик задач не будет выделять потоки для всех этих задач одновременно. Вы закончите тем, что работает только подмножество, а остальные ждут, пока они не будут завершены. Вы никак не можете реорганизовать свой код? - person GazTheDestroyer   schedule 21.05.2012Task
, так иParallel
). В лучшем случае вы просите выбрать между меньшим из двух серьезных зол. - person Aaronaught   schedule 21.05.2012