#net #многопоточность #проектирование
Имеется задача вычислительного характера. Предположительно программа будет исполнятся на машине с многоядерным процессором (процессорами), количество ядер неизвестно заранее. Вопрос: стоит ли программно определять количество ядер (к примеру с помощью System.Environment.ProcessorCount) и создавать соответствующее количество потоков, в которых и будут производится вычисления, или никакого выигрыша в продуктивности подобным образом получить не удаться?
Ответы
Ответ 1
Стоит. Если система может выполнять одновременно 2 потока, а вы будете запускать, к примеру, 4, то лишние 2 потока не добавят эффективности. Если же система может выполнять больше потоков, чем вы создадите, то вы потеряете в эффективности - вычислительные ресурсы (оставшиеся ядра cpu) будут простаивать. Если задача распараллеливается - ее нужно распараллеливать настолько, насколько это возможно. Конечно, о здравом смысле тоже не стоит забывать. При увеличении количества потоков рано или поздно будет достигнута та ситуация, когда накладные расходы станут соизмеримыми (или превысят) чистое время вычислений.Ответ 2
Иногда стоит, иногда нет -- это зависит от того, какими библиотеками вы пользуетесь. Например, PLINQ и TPL, насколько я знаю, самостоятельно опрашивают количество процессоров и выставляют нужную привязку потоков. Если же вы по какой-то причине решили выйти на нижний уровень и управлять потоками вручную, вам, конечно, придётся учитывать количество ядер в системе. Учтите, что стратегия по количеству потоков зависит от вашей задачи. Если вы пишете числомолотилку, количество потоков большее чем количество ядер обычно не имеет смысла.Ответ 3
Зависит от задачи. Вернее, от того, насколько эта задача имеет способность параллелиться. Ну и, само-собой - от Вас: на сколько Вы готовы заниматься планированием этой задачи на ядрах. Зачастую, существует больше попутных препятствий, чем преимуществ, которые сводят на нет попытки грамотно спланировать задачу на всех ядрах одновременно. В первую очередь - это память, которая, как правило требуется для сохранения результатов. Не всегда ее можно расчитать сразу, приходится задачу делить на 2: расчет ресурсов и решение самой задачи. У меня есть только одна успешная реализация, когда эти 2 задачи получилось решать параллельно на одном пуле потоков без дополнительных издержек. Даже не спрашивайте, сколько времени ушло на ее планирование - много. Во вторую очередь - равномерное распределение нагрузки на все ядра. Вы же не думаете, что просто разделив задачу на n частей, Вы получите увеличение производительности в n раз. Вы можете не получить даже удвоения производительности, если не подумаете об этом шаге. Синхронизация частичных результатов: если Вы распределяете нагрузку, значит у Вас есть масса частичных результатов, которые нужно либо где-то хранить, либо куда-то сливать. Это еще одно узкое место такой реализации. Ну и синхронизация с пользователем, естественно. Это целая эпопея. Вот если Вы готовы к такой "неожиданной" прибавке забот - вперед!
Комментариев нет:
Отправить комментарий