Я пытаюсь ускорить расчеты с помощью 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
, но это должно составлять только крошечную крошечную долю общего времени в параллельном цикле.
В выпуске Release build (установлен флаг "оптимизировать код" ) последовательный цикл for
занимает 33,7 с на моем компьютере, тогда как цикл Parallel.For
занимает 8,4 с, а коэффициент производительности - всего 4.0.
В диспетчере задач я вижу, что во время последовательного вычисления загрузка процессора составляет 10-11%, тогда как при параллельном вычислении это составляет всего 70%. Я попытался явно установить
ParallelOptions.MaxDegreesOfParallelism = Environment.ProcessorCount
но безрезультатно. Мне непонятно, почему не все мощности процессора назначаются параллельному вычислению?
Я заметил, что аналогичный вопрос был поднят на SO до, с еще более неутешительным результатом. Однако этот вопрос также связан с неполным распараллеливанием в сторонней библиотеке. Моя основная проблема заключается в распараллеливании основных операций в основных библиотеках.
UPDATE
В некоторых комментариях было указано, что процессор, который я использую, имеет только 4 физических ядра, которые видны системе как 8 ядер, если включена гиперпоточность. Ради этого я отключил гиперпоточность и повторный бенчмаркинг.
С отключением hyper-threading мои вычисления теперь быстрее, как параллельный, так и последовательный цикл for
(как я думал). Использование ЦП в цикле for
составляет ок. 45% (!!!) и 100% во время цикла Parallel.For
.
Время вычисления для цикла for
15,6 с (более чем в 2 раза быстрее, чем при включенной гиперпотоке) и 6.2 с для Parallel.For
(на 25% лучше, чем при включенной гиперпотоке). Соотношение производительности с Parallel.For
теперь только 2,5, работающее на 4 реальных ядрах.
Таким образом, коэффициент производительности по-прежнему значительно ниже ожидаемого, несмотря на то, что гиперпоточность отключена. С другой стороны, интригует, что загрузка процессора настолько высока во время цикла for
? Может ли быть какая-то внутренняя распараллеливание в этом цикле?