Como obter o paralelismo máximo e utilizar a CPU máxima com o Parallel.ForEach?

Existe uma função C #A(arg1, arg2) que precisa ser chamado muitas vezes. Para fazer isso mais rápido, estou usando programação paralela.

Veja o exemplo do seguinte código:

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
    }
});

Agora, o problema é que isso não está aumentando com um aumento no número de núcleos; por exemplo. em 8 núcleos está usando 80% da CPU e em 16 núcleos está usando 40-50% da CPU. Eu quero usar a CPU ao máximo.

Você pode assumirA(arg1, arg2) internamente contém um cálculo complexo, mas não possui operações de E / S ou de rede, e também não há bloqueio de encadeamento. Quais são outras possibilidades para descobrir qual parte do código está fazendo com que ele não funcione de maneira 100% paralela?

Também tentei aumentar o grau de paralelismo, por ex.

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

Mas não ajudou em nada.

Atualização 1 - se eu executar o mesmo código substituindoA() com uma função simples que calcula o número primo, utiliza 100 CPU e aumenta a escala. Portanto, isso prova que outro trecho de código está correto. Agora, o problema pode estar dentro da função originalA(). Eu preciso de uma maneira de detectar esse problema que está causando algum tipo de seqüenciamento.

questionAnswers(1)

yourAnswerToTheQuestion