Неутешительная производительность с Parallel.For
Я пытаюсь ускорить вычисление, используяParallel.For
. У меня процессор Intel Core i7 Q840 с 8 ядрами, но мне удается получить коэффициент производительности только 4 по сравнению с последовательнымfor
петля. Это так хорошо, как можно получить сParallel.For
, или можно ли настроить вызов метода для увеличения производительности?
Вот мой тестовый код, последовательный:
var loops = 200;
var perloop = 10000000;
var sum = 0.0;
for (var k = 0; k < loops; ++k)
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
}
и параллельно:
sum = 0.0;
Parallel.For(0, loops,
k =>
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
});
Цикл, который я распараллеливаю, включает вычисления с «глобально» определенной переменной,sum
, но это должно составлять лишь крошечную долю общего времени в параллельном цикле.
В выпуске сборки (установлен флаг «оптимизировать код») последовательныйfor
loop на моем компьютере занимает 33,7 с, тогда какParallel.For
цикл занимает 8,4 с, коэффициент производительности всего 4,0.
В диспетчере задач видно, что загрузка ЦП составляет 10-11% при последовательном вычислении, тогда как при параллельном вычислении - только 70%. Я пытался явно установить
ParallelOptions.MaxDegreesOfParallelism = Environment.ProcessorCount
но безрезультатно. Мне не понятно, почему не вся мощность процессора назначается напараллельн расчет?
Я заметил, что аналогичный вопрос был поднят на SOд, с еще более разочаровывающим результатом. Однако этот вопрос также включал низкое распараллеливание в сторонней библиотеке. Моя главная задача - распараллеливание основных операций в основных библиотеках.
ОБНОВИТ
Мне было указано в некоторых комментариях, что используемый мной процессор имеет только 4 физических ядра, что видно для системы как 8 ядер, если включена гиперпоточность. Ради этого я отключил гиперпоточность и провел повторный тест.
С гиперпоточностьюотключе, мои расчеты сейчасБыстре, как параллельная, так и (то, что я думал, была) последовательнаяfor
петля. Загрузка процессора во времяfor
цикл до прибл. 45% (!!!) и 100% во времяParallel.For
петля.
Время вычислений дляfor
цикл 15,6 с (более чем в два раза быстрее, чем при гиперпоточности Включен) и 6,2 с дляParallel.For
(На 25% лучше, чем при гиперпоточности Включен). Соотношение производительности сParallel.For
теперь только 2.5, работает на 4 реальных ядрах.
Так что коэффициент производительности по-прежнему значительно ниже, чем ожидалось, несмотря на отключение гиперпоточности. С другой стороны, это интригует, что загрузка процессора настолько высока во времяfor
петля? Может ли в этом цикле происходить какое-то внутреннее распараллеливание?