Parallel.For использует все потоки на 4-жильной / 8-нить, но только 35% нитей на 16-ядерном / 32-нитном [дубликат]

Вы должны посмотреть на инверсию управления:

В таком сценарии вы не будете писать это:

IInterface classRef = new ObjectWhatever();

Вы бы написали что-то вроде этого:

IInterface classRef = container.Resolve();

Это приведет к установке на основе правил в объекте container и построит для вас фактический объект, который может быть ObjectWhatever. Важно то, что вы могли бы заменить это правило тем, что вообще использовали другой тип объекта, и ваш код все равно будет работать.

Если мы покинем IoC из таблицы, вы можете написать код, который знает, что это может разговаривать с объектом , который делает что-то конкретное , но не тот тип объекта или как он это делает.

Это было бы полезно при передаче параметров.

Что касается вашего вопроса в скобках «Также, как вы могли написать метод, который принимает объект, реализующий интерфейс? Возможно ли это?», на C # вы просто используете тип интерфейса для типа параметра, например:

public void DoSomethingToAnObject(IInterface whatever) { ... }

Это подключается прямо к «разговору с объектом, который делает что-то конкретное». Метод, определенный выше, знает, чего ожидать от объекта, что он реализует все на IInterface, но ему не важно, какой тип объекта он есть, только тот, который он придерживается в контракте, что является интерфейсом.

Например, вы, вероятно, знакомы с калькуляторами и, вероятно, использовали довольно много в свои дни, но большую часть времени они все разные. С другой стороны, вы знаете, как должен работать стандартный калькулятор, поэтому вы можете использовать их все, даже если вы не можете использовать специальные функции, которые каждый калькулятор имеет, что ни у кого нет.

Это красота интерфейсов. Вы можете написать фрагмент кода, который знает, что он получит переданные ему объекты, от которых он может ожидать определенного поведения. Ему не важно, какой именно объект он хочет, только потому, что он поддерживает требуемое поведение.

Позвольте мне привести конкретный пример.

У нас есть пользовательская система перевода окон. Эта система проходит через элементы управления в форме и преобразует текст в каждый. Система знает, как обрабатывать базовые элементы управления, такие как свойство type-of-of-control-that-a-Text-свойство и аналогичные базовые элементы, но для чего-то базового оно не подходит.

Теперь , поскольку элементы управления наследуют от заранее определенных классов, которые мы не контролируем, мы могли бы сделать одну из трех вещей:

  1. Построить поддержку нашей системы перевода, чтобы определить, какой тип управления он работает с помощью и перевести правильные биты (кошмар обслуживания)
  2. Построить поддержку в базовых классах (невозможно, поскольку все элементы управления наследуются от разных заранее определенных классов)
  3. Добавить поддержку интерфейса

Итак, мы сделали nr. 3. Все наши элементы управления реализуют ILocalizable, который является интерфейсом, который дает нам один метод, способность переводить «сам» в контейнер текста перевода / правил. Таким образом, форма не должна знать, какой вид управления она обнаружила, только то, что она реализует конкретный интерфейс, и знает, что существует метод, в котором он может вызвать локализацию элемента управления.

8
задан malkam 24 August 2015 в 17:29
поделиться

2 ответа

Параллелизация выполняется во время выполнения, исходя из текущих условий и множества других обстоятельств. Вы не можете заставить .NET использовать все ядра (по крайней мере, в управляемом коде).

Из MSDN :

"И наоборот, по умолчанию Параллельный .ForEach и Parallel.For методы могут использовать переменное количество задач. Вот почему, например, класс ParallelOptions имеет свойство MaxDegreeOfParallelism вместо свойства «MinDegreeOfParallelism». Идея состоит в том, что система может использовать меньше потоков, чем запрашивается для обработки цикл. Пул потоков .NET динамически адаптируется к изменяющимся рабочим нагрузкам, позволяя с течением времени изменять количество рабочих потоков для параллельных задач. Во время выполнения система наблюдает, увеличивает ли количество потоков улучшает или ухудшает общую пропускную способность и корректирует количество соответствующих рабочих потоков.

Будьте осторожны, если вы используете параллельные циклы с отдельными шагами, которые занимают несколько секунд или более. Это может происходить с нагрузками, связанными с I / O, и длительными вычислениями. Если петли принимают долгое время вы можете испытывать неограниченный рост wo rker из-за эвристики для предотвращения потокового голодания, которая используется логикой впрыска класса .NET ThreadPool. "

1
ответ дан Dexion 22 August 2018 в 11:11
поделиться

Из MSDN

По умолчанию For и ForEach будут использовать столько потоков, которые предоставляет базовый планировщик, поэтому изменение MaxDegreeOfParallelism по умолчанию ограничивает количество одновременных задач будет использован.

Способ чтения документации: если базовый планировщик предлагает только один поток, то установка MaxDegreeOfParallelism > 1 все равно приведет к одному потоку.

1
ответ дан theB 22 August 2018 в 11:11
поделиться
  • 1
    Было создано несколько потоков / задач. Но они работают только на 4 ядрах, когда доступно 8 ядер. – malkam 24 August 2015 в 18:00
  • 2
    Планировщик пула и среда выполнения / TPL фактически решают, какие потоки выполняются где и когда. Если время выполнения только запланировано на 4 логических ядра, то это число, которое будет выполняться одновременно, независимо от количества созданных потоков. – theB 24 August 2015 в 18:45
Другие вопросы по тегам:

Похожие вопросы: