Debo usar ThreadPools o la Biblioteca Paralela de tareas para operaciones vinculadas a IO
En uno de mis proyectos que es un poco un agregador, analizo feeds, podcasts y así de la web.
Si utilizo el enfoque secuencial, dado que un gran número de recursos, se necesita bastante tiempo para procesar todos ellos (debido a problemas de red y cosas similares);
foreach(feed in feeds)
{
read_from_web(feed)
parse(feed)
}
Así que quiero implementar concurrencia y no pude decidir si debería usar básicamente ThreadPools para procesar con worker threads o simplemente confiar en TPL para ordenarlo.
ThreadPools seguro que lo hará maneje el trabajo por mí con hilos de trabajo y obtendré lo que espero (y en entornos de CPU multinúcleo, los otros núcleos también se utilizarán).
Pero todavía quiero considerar TPL también, ya que es el método de recomendación, pero estoy un poco preocupado por él. En primer lugar, sé que TPL utiliza ThreadPools pero agrega una capa adicional de toma de decisiones. Me preocupa sobre todo la condición de que donde un entorno de un solo núcleo está presente. Si no me equivoco TPL comienza con un número worker-threads igual al número de núcleos CPU disponibles al principio. Temo que el TPL produzca resultados similares al enfoque secuencial para mi caso vinculado a IO.
Entonces, para las operaciones vinculadas a IO (en mi caso leyendo recursos de la web), ¿es mejor usar ThreadPools y controlar las cosas, o mejor simplemente confiar en TPL? ¿Se puede utilizar TPL también en escenarios vinculados a IO?
Actualización : Mi principal preocupación es que TP en un entorno de CPU de un solo núcleo TPL se comportará como ¿enfoque secuencial o seguirá ofreciendo concurrencia? Ya estoy leyendo Programación Paralela con Microsoft.NET y así el libro pero no pude encontrar una respuesta exacta para esto.
Nota: esta es una reformulación de mi pregunta anterior [ ¿Es posible usar la concurrencia de subprocesos y el paralelismo juntos?] que estaba bastante mal expresado.
6 answers
Así que decidí escribir pruebas para esto y verlo en datos prácticos.
Leyenda de ensayo
- Itr: Iteración
- Seq: Enfoque secuencial.
- PrlEx: Extensiones paralelas - Paralelas.ForEach
- TPL: Biblioteca paralela de tareas
- TPool: ThreadPool
Resultados de las pruebas
CPU de un solo núcleo [Win7-32 ] runs se ejecuta bajo VMware {
Test Environment: 1 physical cpus, 1 cores, 1 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________
Itr. Seq. PrlEx TPL TPool
________________________________________________________________________________
#1 10.82s 04.05s 02.69s 02.60s
#2 07.48s 03.18s 03.17s 02.91s
#3 07.66s 03.21s 01.90s 01.68s
#4 07.43s 01.65s 01.70s 01.76s
#5 07.81s 02.20s 01.75s 01.71s
#6 07.67s 03.25s 01.97s 01.63s
#7 08.14s 01.77s 01.72s 02.66s
#8 08.04s 03.01s 02.03s 01.75s
#9 08.80s 01.71s 01.67s 01.75s
#10 10.19s 02.23s 01.62s 01.74s
________________________________________________________________________________
Avg. 08.40s 02.63s 02.02s 02.02s
________________________________________________________________________________
CPU de un solo núcleo [WinXP ] runs se ejecuta bajo VMware {
Test Environment: 1 physical cpus, NotSupported cores, NotSupported logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________
Itr. Seq. PrlEx TPL TPool
________________________________________________________________________________
#1 10.79s 04.05s 02.75s 02.13s
#2 07.53s 02.84s 02.08s 02.07s
#3 07.79s 03.74s 02.04s 02.07s
#4 08.28s 02.88s 02.73s 03.43s
#5 07.55s 02.59s 03.99s 03.19s
#6 07.50s 02.90s 02.83s 02.29s
#7 07.80s 04.32s 02.78s 02.67s
#8 07.65s 03.10s 02.07s 02.53s
#9 10.70s 02.61s 02.04s 02.10s
#10 08.98s 02.88s 02.09s 02.16s
________________________________________________________________________________
Avg. 08.46s 03.19s 02.54s 02.46s
________________________________________________________________________________
CPU de doble núcleo [Win7-64]
Test Environment: 1 physical cpus, 2 cores, 2 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________
Itr. Seq. PrlEx TPL TPool
________________________________________________________________________________
#1 07.09s 02.28s 02.64s 01.79s
#2 06.04s 02.53s 01.96s 01.94s
#3 05.84s 02.18s 02.08s 02.34s
#4 06.00s 01.43s 01.69s 01.43s
#5 05.74s 01.61s 01.36s 01.49s
#6 05.92s 01.59s 01.73s 01.50s
#7 06.09s 01.44s 02.14s 02.37s
#8 06.37s 01.34s 01.46s 01.36s
#9 06.57s 01.30s 01.58s 01.67s
#10 06.06s 01.95s 02.88s 01.62s
________________________________________________________________________________
Avg. 06.17s 01.76s 01.95s 01.75s
________________________________________________________________________________
CPU de cuatro núcleos [Win7-64] Supported Compatible con HyprerThreading {
Test Environment: 1 physical cpus, 4 cores, 8 logical cpus.
Will be parsing a total of 10 feeds.
________________________________________________________________________________
Itr. Seq. PrlEx TPL TPool
________________________________________________________________________________
#1 10.56s 02.03s 01.71s 01.69s
#2 07.42s 01.63s 01.71s 01.69s
#3 11.66s 01.69s 01.73s 01.61s
#4 07.52s 01.77s 01.63s 01.65s
#5 07.69s 02.32s 01.67s 01.62s
#6 07.31s 01.64s 01.53s 02.17s
#7 07.44s 02.56s 02.35s 02.31s
#8 08.36s 01.93s 01.73s 01.66s
#9 07.92s 02.15s 01.72s 01.65s
#10 07.60s 02.14s 01.68s 01.68s
________________________________________________________________________________
Avg. 08.35s 01.99s 01.75s 01.77s
________________________________________________________________________________
Resumen
- Ya sea que se ejecute en un entorno de un solo núcleo o en uno de varios núcleos, Parallel Extensions, TPL y ThreadPool se comportan de la misma manera y dan resultados aproximados.
- Siendo TPL tiene ventajas, como fácil manejo de excepciones, cancelación y apoyo capacidad de devolver fácilmente los resultados de la tarea. Aunque Extensiones paralelas es también otra alternativa viable.
Ejecutar pruebas por su cuenta
Puede descargar la fuente aquí y ejecutar por su cuenta. Si puedes publicar los resultados, también los agregaré.
Actualización: Corregido el enlace fuente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-11 09:50:09
Si está tratando de maximizar el rendimiento de las tareas vinculadas a IO, absolutamente debe combine las API tradicionales del Modelo de Procesamiento Asíncrono (APM) con su trabajo basado en TPL. Las APIs APM son la única manera de desbloquear el subproceso de CPU mientras la devolución de llamada de IO asíncrona está pendiente. El TPL proporciona el método auxiliar TaskFactory::FromAsync
para ayudar a combinar el código APM y TPL.
Echa un vistazo a esta sección del SDK. NET en MSDN titulado TPL y. NET tradicional Programación asíncrona para obtener más información sobre cómo combinar estos dos modelos de programación para lograr el nirvana asíncrono.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-08 01:28:41
Tiene razón en que el TPL elimina parte del control que tiene cuando crea su propio grupo de subprocesos. Pero esto solo es correcto si no quieres profundizar. El TPL le permite crear tareas de larga duración que no son parte del grupo de subprocesos de TPL y podrían servir bien a su propósito. El libro publicado que es una lectura libre Programación paralela con Microsoft.NET le dará mucho más información sobre cómo se debe usar el TPL. Siempre tienes la opción de dar Paralelo.Para, Tareas explicit parámetros cuántos hilos se deben asignar. Además de esto, puede reemplazar el programador de TPL con el suyo propio si desea un control total.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 22:30:35
Puede asignar su propio programador de tareas a una tarea TPL. Sin embargo, el trabajo predeterminado robar es bastante inteligente.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 22:26:34
Temo que el TPL produzca resultados similares al enfoque secuencial para mi caso vinculado a IO.
Creo que lo hará. ¿Cuál es el cuello de botella? ¿Está analizando o descargando? Multithreading no le ayudará mucho con la descarga de la web.
Usaría la Biblioteca de tareas Paralelas para recortar, aplicar máscara o efectos para las imágenes descargadas, cortar alguna muestra de podcast, etc. Es más escalable.
Pero no será el orden de magnitud acelerar. Gasta tu recursos para implementar algunas características, pruebas.
PS. "Wow mi función se ejecuta en 0.7 s en lugar de 0.9";)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-06 22:15:24
Si paraleliza sus llamadas a las URL, creo que mejorará su aplicación, incluso si solo tiene un núcleo. Echa un vistazo a este código:
var client = new HttpClient();
var urls = new[]{"a", "url", "to", "find"};
// due to the EAP pattern, this will run in parallel.
var tasks = urls.Select(c=> client.GetAsync(c));
var result = Tasks.WhenAll(task).ContinueWith(a=> AnalyzeThisWords(a.Result));
result.Wait(); // don't know if this is needed or it's correct to call wait
La diferencia entre multihilo y asincronía en este caso es cómo se realiza la devolución de llamada/finalización.
Cuando se usa EAP, el número de tareas no está relacionado con el número de subprocesos.
Al confiar en la tarea GetAsync, el cliente http usa un networkstream (socket, cliente tcp o lo que sea) y lo señala para elevar un evento cuando se realiza BeginRead/EndRead. Por lo tanto, no hay hilos involucrados en este momento.
Después de que se llame a la finalización, tal vez se cree un nuevo subproceso, pero depende de TaskScheduler (utilizado en la llamada GetAsync/ContinueWith call) crear un nuevo subproceso, usar un subproceso existente o insertar la tarea para usar el subproceso de llamada.
Si el AnalyzeThisWords
se bloquea durante demasiado tiempo, entonces comienza a obtener cuellos de botella a medida que la" devolución de llamada " en el ContinueWith se realiza desde un grupo de subprocesos trabajador.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 01:31:00