2010-02-23 18 views
13

Tengo una aplicación que consume mucha CPU. Cuando los datos se procesan en un solo subproceso, el uso de la CPU va al 100% durante muchos minutos. De modo que el rendimiento de la aplicación parece estar limitado por la CPU. He multipli- cado la lógica de la aplicación, lo que resulta en un aumento del rendimiento general. Sin embargo, el uso de CPU apenas supera el 30% -50%. Esperaría que la CPU (y los muchos núcleos) llegaran al 100% ya que procesé muchos datos al mismo tiempo.¿Cuáles son las razones por las cuales el uso de la CPU no llega al 100% con C# y APM?

A continuación se muestra un ejemplo simplificado de la lógica que uso para iniciar los hilos. Cuando ejecuto este ejemplo, la CPU pasa al 100% (en una máquina de 8/16 núcleos). Sin embargo, mi aplicación que usa el mismo patrón no.

public class DataExecutionContext 
{ 
    public int Counter { get; set; } 

    // Arrays of data 
} 

static void Main(string[] args) 
{ 
    // Load data from the database into the context 
    var contexts = new List<DataExecutionContext>(100); 
    for (int i = 0; i < 100; i++) 
    { 
     contexts.Add(new DataExecutionContext()); 
    } 

    // Data loaded. Start to process. 
    var latch = new CountdownEvent(contexts.Count); 
    var processData = new Action<DataExecutionContext>(c => 
    { 
     // The thread doesn't access data from a DB, file, 
     // network, etc. It reads and write data in RAM only 
     // (in its context). 
     for (int i = 0; i < 100000000; i++) 
      c.Counter++; 
    }); 

    foreach (var context in contexts) 
    { 
     processData.BeginInvoke(context, new AsyncCallback(ar => 
     { 
      latch.Signal(); 
     }), null); 
    } 

    latch.Wait(); 
} 

He reducido el número de bloqueos al mínimo estricto (solo el seguro está bloqueado). La mejor manera que encontré fue crear un contexto en el cual un hilo puede leer/escribir en la memoria. Los contextos no se comparten entre otros hilos. Los hilos no pueden acceder a la base de datos, archivos o red. En otras palabras, hice un perfil de mi aplicación y no encontré ningún cuello de botella.

¿Por qué el uso de la CPU de mi aplicación no es del 50%? ¿Es el patrón que uso? ¿Debo crear mi propio hilo en lugar de usar el grupo de hilos de .Net? ¿Hay algún problema? ¿Hay alguna herramienta que me puedas recomendar para encontrar mi problema?

Gracias!

+0

posible, aunque poco probable sería que el código está provocando una gran cantidad de recolección de basura, que requiere cierta cantidad de sincronización. –

Respuesta

6

Hay muchas cosas que podrían, potencialmente, causar este comportamiento.

Primero, ¿qué tipo de CPU tienes? Si tiene un procesador i7 o similar, el sistema operativo verá que tiene 8 núcleos, cuando en realidad tiene 4 núcleos con 2 hyperthreads/core. Para la mayoría de las operaciones, hyperthreading realmente no proporciona la misma escalabilidad que un segundo núcleo, aunque el sistema operativo lo vea de esta manera. He tenido esto porque mi uso general de la CPU parece más bajo en el sistema operativo ...

En segundo lugar, es posible que haya alguna forma de compartir en tiempo real. Menciona que tiene bloqueo: incluso si se mantiene al mínimo, los bloqueos pueden impedirle programar esto de manera efectiva.

Además, en este momento, está programando los 100 elementos de trabajo, justo al frente. El sistema operativo tendrá que ingresar y sacar esos 100 hilos. Es posible que desee restringir esto a solo permitir que un cierto número procese en un momento dado. Esto es mucho más fácil usando la nueva Biblioteca de tareas paralelas (simplemente use Parallel.ForEach con una configuración ParallelOptions para tener un número máximo de hilos), pero puede hacerlo usted mismo.

Dado que está programando los 100 elementos para procesar simulatáneamente, la búsqueda puede estar obstaculizando la capacidad de obtener el máximo rendimiento.

Además, si está realizando otro trabajo "más real", es posible que tenga problemas para compartir información falsa, especialmente si está trabajando con matrices o colecciones que se comparten (incluso si los elementos que se procesan son no compartido).

Recomendaría ejecutar esto en el simulador de simultaneidad en VS 2010 - le dará una idea mucho más clara de lo que está sucediendo.

+0

Probé en muchas máquinas: Core Duo (uso ~ 80-90%), i7 (uso ~ 50%), Dual Xeon L5520 (uso ~ 40-50%). – Martin

+0

Dado que tiene un 80-90% en el núcleo y más bajo en los demás, parece que tiene problemas de uso falso o verdadero. El intercambio falso puede estar ocurriendo si intenta usar datos que están demasiado apretados en la memoria, desde múltiples hilos. El intercambio real se debe al bloqueo ... –

+1

Encontré ese artículo en MSDN sobre False Sharing (http: // msdn. microsoft.com/en-us/magazine/cc872851.aspx) y parece que podría ser mi problema ... Todavía no estoy seguro de entender completamente False Sharing. ¿Cómo resolviste esto? – Martin

2

Esto es una especulación sin ver su aplicación, pero si su aplicación está procesando archivos, bases de datos, creando muchos objetos (solicitando memoria), trabajando con dispositivos de red o dispositivos de hardware de cualquier tipo, entonces esos factores podría estar limitando su aplicación para que no llegue al 100% de uso de la CPU. Esto combinado con el cambio de hilo también puede ser un factor.

Dice que está utilizando el patrón del ejemplo que dio, pero dice que el ejemplo alcanza el 100% de utilización pero su aplicación no. Entonces hay algo de diferencia allí, y debería tratar de describir con más detalle lo que está haciendo su aplicación. 50% de utilización no está mal. Muchas aplicaciones se ejecutan al 50% en las CPU Intel con subprocesos múltiples y todavía funcionan bien. Si la aplicación no está alcanzando el 100% de utilización de la CPU y todavía está obteniendo un buen rendimiento, entonces diría que en realidad es algo bueno, porque significa que tiene algo de espacio libre ya que ya no está unida a la CPU. Esto significa casos en que otras cosas pueden tomar tiempo de CPU, por lo que su aplicación no se verá tan afectada. Si estuviese al 100% de utilización, vería el rendimiento de las aplicaciones vacilarse cuando otros procesos utilicen activamente la CPU.

0

si usted está haciendo un montón de pequeñas asignaciones de memoria - montón administrado puede convertirse en un recurso compartido que bloquea los hilos y ralentiza el proceso y por lo tanto el uso de CPU

Cuestiones relacionadas