2014-10-26 4 views
4

У меня проблема с моей библиотекой для нейронных сетей. Он использует многопоточность для фиксации вычислений. Но примерно через 30-60 секунд времени выполнения моя программа больше не использует 100% моих i7 3610QM 4cores 8threads.Как объяснить это странное поведение parallel.for (C#)

В основном моя обработка выглядит (C# с псевдокодом)

for each training example t in training set 
    for each layer l in neural network 
     Parallel.For(0, N, (int i)=>{l.processForward(l.regions[i])}) 
    for each layer l in neural network (but with reversed order) 
     Parallel.For(0, N, (int i)=>{l.backPropageteError(l.regions[i])}) 

Где регионы список слоя из предвычисленных областей нейрона для обработки. Каждый регион имеет одинаковый размер 1/N текущего слоя, поэтому Задачи имеют такой же размер, чтобы минимизировать вероятность того, что другим потокам придется ждать завершения самой продолжительной задачи.

Как я уже сказал, эта схема обработки потребляет 100% моего процессора только на короткое время, а затем падает до 80-85%. В моем случае я установил N в Environment.ProcessorsCount (= 8);

Я могу обменять весь код/​​репозиторий, если кто-то хочет помочь.

Я попытался исследовать, и я создал новый проект консоли и положил туда почти Hello World of Parallel.For(), и я просто не могу сказать, что происходит. Это может быть другая проблема Parallel.For(), но я также хочу, чтобы вы решили эту проблему. Вот код:

class Program 
{ 
    static void Main(string[] args) 
    { 
     const int n = 1; 

     while (true) 
     { 
      //int counter = 0; for (int ii = 0; ii < 1000; ++ii) counter++; 

      Parallel.For(0, n, (int i) => { int counter = 0; for (int ii = 0; ii < 1000; ++ii) counter++; }); 
     } 

    } 
} 

В этом коде я постоянно (в то время как петля) создать одну задачу (п = 1), что имеет какую-то работу, чтобы сделать (увеличить счетчик одну тысячу раз). Как я знаю, Parallel.For блокирует выполнение/ожидает завершения всех параллельных вызовов. Если это так, то он должен выполнять ту же работу, что и раздел комментариев (при условии n = 1). Но на моем компьютере эта программа использует 100% процессора, например, есть работа для нескольких потоков! Как это возможно? Когда я переключаюсь на прокомментированную версию, в программе используется менее 20% процессора, и это то, что я ожидал. Пожалуйста, помогите мне понять это поведение.

+0

Насколько я понимаю Parallel.For это для выполнения __work__ в параллельных потоках. В вашем примере в этих циклах выполняется __no__. Хороший компилятор полностью удалит их, поскольку они не выдают результат. Также установка DegreeOfParallelization на 100% не является хорошей идеей, так или иначе imo; 90% должны быть достаточно хорошими и держать систему в приятной реакции. - Также держите __cost__ в параллельном понимании! – TaW

+0

Здесь недостаточно информации, чтобы ответить на ваш первый вопрос. И ваш второй код будет тратить большую часть своего времени на синхронизацию. Попробуйте изменить его на 'ii <100000000'. – svick

+0

Parallel.For был ранним, у него проблемы с учебным колесом. Покрыто в [этой записи] (http://stackoverflow.com/a/25950320/17034). –

ответ

0

Как сказал @TaW, их стоимость идет параллельно. Вот почему f() и Parallel.For(0, n, _ => f()) не являются эквивалентными. Параллельная версия предусматривает планирование потоков и переключение контекста. В вашем случае время выполнения f() сопоставимо с накладными расходами на потоки. Это приводит к ухудшению производительности с параллельной версией. Parallel.For дождаться завершения операции, но завершается так быстро, что в течение очень короткого периода времени на процессор запускается несколько потоков (помните, что каждый раз, когда вы вызываете Parallel.For, он может выбрать другой поток для запуска f() на нем) на разных ядрах ЦП.

Что касается первой части вопроса, я думаю, проблема заключается в диапазоне индексов, переданных в Parallel.For. Вместо [0, количество ядер процессора] он должен быть равен диапазону индексов данных.

+0

Хорошо, теперь я понимаю вторую проблему. Я имею в виду, что 1000-итерация - это небольшая работа в примере выше, и использование parallel.for создает много возможностей для многих потоков, поэтому я получаю 100% -ное использование ЦП даже при n = 1. Что я не понимаю, производительность снижается со временем примерно до 80%.Это не моя система (выигрыш 8.1), потому что, когда я выполняю пример выше (вместо моего реального кода библиотеки), я получаю постоянное 100% использование ЦП. Пример работает с n = Environment.processorCount и итерацией в цикле 1 000 000. Это дает хороший 100% -ный отказ от использования, чего я могу пропустить? –

+0

Я прочитал первую часть вопроса еще раз и теперь не знаю, как используется 'Parallel.For'. Как возможно, что размер 'l.regions' коррелирует с количеством ядер? Я думаю, индекс должен идти от нуля до длины 'l.regions'. Первые два параметра 'Parallel.For' определяют диапазон индексов, а не количество ядер ЦП для запуска кода. – alpinsky

+0

Обновлен ответ. – alpinsky

Смежные вопросы