2012-06-01 13 views
5

Tal vez no entendieron bien ... toda la cuestión de clase paralelo :(Usando System.Threading.Tasks.Parallel crear un nuevo hilo en el grupo de hilos?

Pero de lo que estoy leyendo ahora, entiendo que cuando se utiliza la realidad paralela que movilizar todos los hilos que existe en el ThreadPool para una tarea/misión

por ejemplo:..

var arrayStrings = new string[1000]; 
    Parallel.ForEach<string>(arrayStrings, someString => 
    { 
     DoSomething(someString); 
    }); 

Así que la Parallel.ForEach en este caso es la movilización de todos los hilos que existe en el conjunto de subprocesos para el 'HacerAlgo' tarea/misión

¿Pero la llamada Parallel.ForEach creará un nuevo hilo?

Está claro que no habrá 1000 nuevos hilos. Pero supongamos que hay 1000 nuevos subprocesos, algunos casos en los que el grupo de subprocesos libera todo el hilo que contiene, en este caso ... ¿Parallel.ForEach creará un hilo nuevo?

+0

['Parallel.ForEach'] (http://msdn.microsoft.com/en-us/library/system.threading.taskings.parallel.foreach.aspx) -" Ejecuta un foreach (For Each en Visual Basic) operación en la cual las iteraciones ** pueden ** ejecutarse en paralelo. " –

Respuesta

10

Respuesta corta: Parallel.ForEach() no "moviliza todos los hilos". Y cualquier operación que programe algún trabajo en el ThreadPool (que Parallel.ForEach()) puede provocar la creación de un nuevo subproceso en el grupo.

Respuesta larga: Para entender esto correctamente, es necesario saber cómo tres niveles de abstracción: Parallel.ForEach(), TaskScheduler y ThreadPool:

  1. Parallel.ForEach() (y Parallel.For()) programar su trabajo en un TaskScheduler. Si no especifica un planificador explícitamente, se usará the current one.

    Parallel.ForEach() divide el trabajo entre varios Task s. Cada Task procesará una parte de la secuencia de entrada, y cuando haya terminado, solicitará otra parte si hay una disponible, y así sucesivamente.

    ¿Cuántos Task s Parallel.ForEach() crear? Tantos como TaskScheduler lo dejarán funcionar. La forma en que esto se hace es que cada Task primero pone en cola una copia de sí mismo cuando comienza a ejecutarse (a menos que hacerlo viole MaxDegreeOfParallelism, si lo configura). De esta manera, el nivel de concurrencia real es hasta el TaskScheduler.

    Además, el primer Task se ejecutará realmente en el hilo actual, si el TaskScheduler lo admite (esto se hace usando RunSynchronously()).

  2. The default TaskScheduler simplemente encola cada Task a la cola ThreadPool. (En realidad, es más complicado si inicia Task desde otro Task, pero eso no es relevante aquí.) Otros TaskScheduler s pueden hacer cosas completamente diferentes y algunos de ellos (como TaskScheduler.FromCurrentSynchronizationContext()) son completamente inadecuados para usar con Parallel.ForEach().

  3. El ThreadPool utiliza un algoritmo bastante complejo para decidir exactamente cuántos subprocesos se deben ejecutar en un momento dado. Pero lo más importante aquí es que la programación del nuevo elemento de trabajo puede provocar la creación de un nuevo hilo (aunque no necesariamente de forma inmediata). Y debido a que con Parallel.ForEach(), siempre hay algún elemento en cola para ser ejecutado, depende completamente del algoritmo interno de ThreadPool para decidir el número de subprocesos.

En conjunto, que es más o menos imposible decidir cuántos hilos será utilizado por un Parallel.ForEach(), porque depende de muchas variables. Ambos extremos son posibles: que el ciclo se ejecutará de forma totalmente sincrónica en el hilo actual y que cada elemento se ejecutará por sí mismo, el hilo creado recientemente.

Pero, en general, debe estar cerca de la eficiencia óptima y es probable que no tenga que preocuparse por todos esos detalles.

1

Paralelo.Foreach no crea hilos nuevos, ni "moviliza todos los hilos". Utiliza un número limitado de subprocesos desde el grupo de subprocesos y les envía tareas para la ejecución en paralelo. En la implementación actual, el valor predeterminado es usar un hilo por núcleo.

+1

Eso simplemente no es verdad. Si el código dentro de 'Parallel.ForEach()' bloquea o ejecuta durante un tiempo prolongado, se usarán más hilos que la cantidad de núcleos. – svick

0

Paralelo no trata los hilos en absoluto - programa TAREAS para el marco de tareas. THat tiene un planificador y el planificador predeterminado va al threadpool. Éste tratará de encontrar una buena cantidad de subprocesos (mejor en 4.5 que 4.0) y el Threadpool puede girar lentamente nuevos subprocesos.

Pero eso no es una functoin de parallel.foreach;)

la Parallel.ForEach creará ningún nuevo hilo ???

Nunca lo hará. Como dije, tiene 1000 foreach, luego pone en cola 10.000 tareas, Point. El programador de fábrica de tareas hará lo que está programado para hacer ((puede reemplazarlo). Generalmente, por defecto - sí, lentamente surgen nuevos hilos DENTRO DE LA RAZÓN

+0

'Parallel.ForEach()' en una colección de elementos * n * generalmente no creará * n * 'Tareas, que podrían ser demasiado ineficaces. Particiona la colección de origen y crea solo tantas 'Tareas' como' TaskScheduler' permite ejecutar. – svick

1

Creo que tiene esto al revés de PATTERNS OF PARALLEL PROGRAMMING verá que es el azúcar Parallel.ForEach realmente sintáctica.

el Parallel.ForEach se hierve en gran parte a algo como esto,

for (int p = 0; p < arrayStrings.Count(); p++) 
{ 
    ThreadPool.QueueUserWorkItem(DoSomething(arrayStrings[p]); 
} 

el ThreadPool se encarga de la programación. Hay algunos excelentes artículos sobre cómo se comporta el planificador de ThreadPool en cierto grado Si usted está interesado, eso no tiene nada que ver con TPL.

+1

'new Thread()' siempre creará un nuevo hilo, no usará uno del threadpool.El código que publicó siempre creará tantos hilos como elementos en la colección. Esto de ninguna manera representa Parallel.ForEach. –

+0

@AllonGuralnek estás en lo correcto, actualizado. –

+1

'Parallel.ForEach()' no está construido encima de 'ThreadPool', está construido encima de' TaskScheduler'. Además, es más inteligente sobre el código en cada 'Tarea', por lo que no hay una' Tarea' por artículo. Otra cosa es que tu código no se bloquea, pero 'Parallel.ForEach()' sí. – svick

Cuestiones relacionadas