2009-06-10 9 views
8

Tengo un trabajo vergonzosamente paralelizable en una aplicación de consola .NET 3.5 y quiero aprovechar los procesadores hyperthreading y multi-core. ¿Cómo selecciono el mejor número de subprocesos de trabajo para utilizar cualquiera de estos los mejores en un sistema arbitrario? Por ejemplo, si es un núcleo doble, querré 2 hilos; quad core. Querré 4 hilos. Lo que finalmente busco es determinar las características del procesador para poder saber cuántos hilos crear.¿Cómo elijo la mejor cantidad de hilos para hyptherthreading/multicore?

No estoy preguntando cómo dividir el trabajo ni cómo hacerlo, me pregunto cómo puedo determinar el número "óptimo" de subprocesos en una máquina arbitraria en la que se ejecutará esta aplicación de consola.

+0

El número "óptimo" no es necesariamente la cantidad de procesadores que tiene. Se basa en eso, pero dependiendo de lo que esté haciendo, los hilos no siempre se procesarán, por lo tanto, tener más hilos que procesadores suele ser más eficiente. –

Respuesta

9

Puede utilizar Environment.ProcessorCount si eso es lo único que está buscando. Pero usualmente usar una ThreadPool es la mejor opción.

El grupo de subprocesos .NET también tiene disposiciones para asignar en ocasiones más subprocesos que los que tiene núcleos para maximizar el rendimiento en ciertos escenarios donde muchos subprocesos están esperando a que termine la E/S.

+0

ProcessorCount es de hecho lo que busco. Con respecto a ThreadPool: como mi comentario a Mark, ¿cómo me ayuda ThreadPool si no sé cuántos hilos crear? –

+0

ThreadPool determina por sí mismo cuántos subprocesos usar en un sistema determinado. Básicamente usa la misma propiedad (si no recuerdo mal) a menos que especifique lo contrario. – Joey

+0

Si * sabe * que va a enviar trabajo de inmediato, puede usar ThreadPool.SetMinThreads para el recuento del procesador. – Rick

15

Le sugiero que no intente determinarlo usted mismo. Use ThreadPool y deje que .NET administre los hilos por usted.

+0

Eso realmente no me ayuda para nada. Si creo 4 hilos en un solo núcleo, ninguno de los sistemas hyperthreaded entonces estoy desperdiciando recursos. Si creo 2 hilos en un quad core entonces solo estoy utilizando la mitad del procesador. –

+0

El uso del ThreadPool viene con una sobrecarga, pero también delega la responsabilidad a la parte sensible que maneja la programación de una manera sensata. Es posible que pueda gestionar la administración de memoria mejor que GarbageCollector, por lo que planea implementar su propio recolector de elementos no utilizados. No trataría de adivinar cómo funciona el ThreadPool. – Mark

2

La única forma es una combinación de datos y análisis de código basado en datos de rendimiento.

Diferentes familias de CPU y velocidades vs. velocidad de la memoria frente a otras actividades en el sistema todos van a realizar la puesta a punto diferente.

potencialmente un poco de auto-tuning es posible, pero esto va a significar tener algún tipo de ajuste de rendimiento en vivo y autoajuste.

0

Se puede argumentar que la verdadera manera de elegir el mejor número de hilos es de aplicación a perfilarse de forma adaptativa y cambiar su comportamiento roscado sobre la base de lo que le da el mejor rendimiento.

+0

¡No pensé en eso! Gracias, lo veré para mi proyecto, ya que no está relacionado con la máquina en la que se está ejecutando, sino con un SqlServer remoto. –

1

He leído algo sobre esto recientemente (véase la respuesta aceptada a this question por ejemplo).

La respuesta simple es que deja que el sistema operativo decida. Puede hacer un mejor trabajo al decidir qué es lo mejor que puedes.

Hay una serie de preguntas sobre un tema similar: la búsqueda de "hilos de número óptimo" (sin las comillas) le da un par de páginas de resultados.

0

Escribí una aplicación simple de crujido de números que utilizaba varios subprocesos, y descubrí que en mi sistema Quad-core completaba la mayor parte del trabajo en un período fijo utilizando 6 subprocesos.

Creo que la única manera real de determinarlo es a través de la comprobación o la creación de perfiles.

2

Una buena regla del pulgar, dado que usted está completamente vinculado a la CPU, es processorCount+1.

Eso es porque siempre se obtendrá algunas tareas arrancado/parado/interrumpe y n tareas será casi nunca se llene por completo n procesadores.

+0

¿Alguna idea de por qué el +1? –

+0

+1 porque obtendrá algunas tareas iniciadas/detenidas/interrumpidas y n tareas casi nunca llenarán completamente n procesadores. –

+0

Explique el voto negativo: me gustaría saber qué estoy haciendo mal. Gracias. –

1

Yo diría que también depende de lo que esté haciendo, si hace una aplicación de servidor y usa todo lo que puede de la CPU a través de Environment.ProcessorCount o un grupo de subprocesos es una buena idea. Pero si esto se está ejecutando en un escritorio o en una máquina que no está dedicada a esta tarea, es posible que desee dejar algo de CPU inactiva para que la máquina "funcione" para el usuario.

+0

Es una aplicación de consola ejecutada por el usuario, por lo que quiero reducir el tiempo de ejecución utilizando todos los "procesadores". Sin embargo, ProcessorCount es lo que quiero. –

3

El número óptimo sería simplemente el recuento del procesador. De manera óptima, siempre tendría un hilo ejecutándose en una CPU (lógica o física) para minimizar los cambios de contexto y la sobrecarga que lleva consigo.

Si ese es el número correcto depende (como todo el mundo ha dicho) de lo que está haciendo. The threadpool (si lo entiendo correctamente) prácticamente intenta usar el menor número de subprocesos posible, pero genera uno más cada vez que se bloquea un hilo.

El bloqueo nunca es óptimo, pero si está realizando alguna forma de bloqueo, la respuesta cambiará drásticamente.

La forma más sencilla y fácil de obtener un buen comportamiento (no necesariamente óptimo) es usar el grupo de subprocesos. En mi opinión, es realmente difícil hacer algo mejor que el grupo de temas, por lo que es simplemente el mejor lugar para comenzar y solo pensar en otra cosa si puedes demostrar por qué no es lo suficientemente bueno.

2

O incluso mejor que el ThreadPool, utilice instancias de tareas de .NET 4.0 del TPL. La Biblioteca de tareas paralelas está construida sobre una base en el marco .NET 4.0 que realmente determinará la cantidad óptima de subprocesos para realizar las tareas de la manera más eficiente posible para usted.

4

El número correcto es obviamente 42.

Ahora en la nota seria. Solo usa el grupo de subprocesos, siempre.

1) Si usted tiene una larga procesamiento tarea (es decir. CPU) que puede ser dividida en varias comidas pieza de trabajo, entonces debería particionar su tarea y presentar todos los elementos de trabajo individuales a la ThreadPool. El grupo de subprocesos recogerá los elementos de trabajo y comenzará a producirlos de forma dinámica, ya que tiene capacidades de autocontrol que incluyen iniciar nuevos subprocesos según sea necesario y pueden ser configured at deployment by administrators according to the deployment site requirements, en lugar de precalcular los números en el momento del desarrollo. Si bien es cierto que el tamaño de partición adecuado de su tarea de procesamiento puede tener en cuenta la cantidad de CPU disponibles, la respuesta correcta depende tanto de la naturaleza de la tarea y de los datos que ni siquiera vale la pena mencionar en esta etapa (y además las principales preocupaciones deberían ser su NUMA nodes, localidad de memoria y contención de caché interbloqueada, y solo después de eso, la cantidad de núcleos).

2) Si está realizando E/S (incluidas las llamadas a bases de datos), entonces debe usar E/S asincrónica y completar las llamadas en ThreadPool denominadas rutinas de finalización.

Estas dos son las únicas razones válidas por las que debe tener varios subprocesos, y ambos se manejan mejor con el ThreadPool. Cualquier otra cosa, incluido el inicio de un hilo por 'solicitud' o 'conexión', es de hecho anti patrones en el mundo API de Win32 (fork es un patrón válido en * nix, pero definitivamente no en Windows).

Para una más especializada y forma, la discusión de forma más detallada del tema sólo puedo recomendar los papeles Rick Vicik sobre el tema:

0

Además del recuento del procesador, es posible que desee tener en cuenta la afinidad del procesador del proceso al contar bits en la afinidad máscara devuelta por la función GetProcessAffinityMask.

0

Si no hay un excesivo procesamiento de E/S o llamadas al sistema cuando los subprocesos están en ejecución, entonces el número de subprocesos (excepto el subproceso principal) es en general igual al número de procesadores/núcleos en su sistema, de lo contrario puede intentar aumentar el número de subprocesos probando.

Cuestiones relacionadas