2016-07-07 3 views
7

Существует функция C# A(arg1, arg2), которую нужно называть много раз. Чтобы сделать это быстрее всего, я использую параллельное программирование.Как я могу достичь максимального параллелизма и использовать максимальный процессор с Parallel.ForEach?

Возьмем в качестве примера следующий код:

long totalCalls = 2000000; 
int threads = Environment.ProcessorCount; 

ParallelOptions options = new ParallelOptions(); 
options.MaxDegreeOfParallelism = threads; 

Parallel.ForEach(Enumerable.Range(1, threads), options, range => 
{ 
    for (int i = 0; i < total/threads; i++) 
    { 
     // init arg1 and arg2 
     var value = A(arg1, agr2); 
     // do something with value 
    } 
}); 

Теперь вопрос заключается в том, что это не масштабируется с увеличением количества ядер; например на 8 ядрах он использует 80% процессора, а на 16 ядрах он использует 40-50% CPU. Я хочу использовать процессор в максимальной степени.

Вы можете предположить, что A(arg1, arg2) внутренне содержит комплексный расчет, но он не имеет операций ввода-вывода или сети, а также нет блокировки потоков. Каковы другие возможности, чтобы выяснить, какая часть кода делает его не 100% параллельным?

Я также попытался увеличить степень параллелизма, например.

int threads = Environment.ProcessorCount * 2; 
// AND 
int threads = Environment.ProcessorCount * 4; 
// etc. 

Но это не помогло.

Обновление 1 - если я бегу тот же самый код, заменив A() с простой функцией, которая вычисляет простое число, то оно с использованием 100 процессора и масштабирования хорошо. Таким образом, это доказывает правильность другой части кода. Теперь вопрос может быть в исходной функции A(). Мне нужен способ обнаружить эту проблему, которая вызывает какое-то упорядочение.

+3

не лучше ли вам использовать 'Task' '' Parallel.ForEach'? вы можете лучше контролировать задачи и их количество. – Liam

+2

который os? вы запускаете сборку без vshost.exe? это процесс, который работает только при измерении использования ЦП? приоритет процесса? – dlatikay

+0

@dlatikay - Windows Server 2012. Да, я запускаю сборку релиза, и помимо функций ОС по умолчанию это единственная программа, которая работает. Я не задал приоритет. Позвольте мне попробовать и это. –

ответ

5

Вы обнаружили, что код в A является проблемой.

Существует одна очень распространенная проблема: сбор мусора. Настройте приложение в app.config, чтобы использовать параллельный сервер GC. GC рабочей станции имеет тенденцию сериализовать выполнение. Эффект суровый.

Если это не проблема, переустановите отладчик несколько раз и посмотрите на окно Debug -> Parallel Stacks. Там вы можете видеть, что делают ваши потоки. Ищите общие ресурсы и споры. Например, если вы найдете много потоков, ожидающих блокировки, это ваша проблема.

Другая хорошая технология отладки - это код для комментариев. Как только предел масштабируемости исчезнет, ​​вы знаете, какой код вызвал его.

+0

Я попытался настроить параллельный сервер GC, но пока не удалось. Нет блокировки в 'A()' –

+0

Пробовал ли вы метод отладчика? – usr

+0

Попытка сделать это, но пока не удалась, и по какой-то причине я не могу поделиться тем, что содержит 'A()'. –