¿Cómo puedo lograr el máximo paralelismo y utilizar la CPU máxima con Parallel.ForEach?

Hay una función C #A(arg1, arg2) que necesita ser llamado muchas veces. Para hacer esto más rápido, estoy usando programación paralela.

Tome el ejemplo del siguiente 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
    }
});

Ahora el problema es que esto no está aumentando con un aumento en el número de núcleos; p.ej. en 8 núcleos está utilizando el 80% de la CPU y en 16 núcleos está utilizando el 40-50% de la CPU. Quiero usar la CPU al máximo.

Puedes asumirA(arg1, arg2) internamente contiene un cálculo complejo, pero no tiene operaciones de E / S ni vinculadas a la red, y tampoco hay bloqueo de subprocesos. ¿Cuáles son otras posibilidades para averiguar qué parte del código está haciendo que no funcione de manera 100% paralela?

También intenté aumentar el grado de paralelismo, p.

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

Pero no fue de ayuda.

Actualización 1 - si ejecuto el mismo código reemplazandoA() con una función simple que está calculando el número primo, entonces está utilizando 100 CPU y escalando bien. Entonces esto prueba que otro fragmento de código es correcto. Ahora el problema podría estar dentro de la función originalA(). Necesito una forma de detectar ese problema que está causando algún tipo de secuencia.

Respuestas a la pregunta(1)

Su respuesta a la pregunta