Parallel Computing with .NET 4.0
Sacando partido al multi-core
Lluís Franco - AndorraDotNet
Agenda
1. Programación paralela ¿Queéloqueé?
2. Un poco de historia y algunos conceptos.
3. ¿Multithreading versus Paralle...
Let’s play!
Parallel Computing with .NET 4.0
3
1 - ¿Y eso queéloqueé?
¿Esto?
4
1 - ¿Y eso queéloqueé?
¿Acaso esto?
5
1 - ¿Y eso queéloqueé?
Wikipedia dixit:
“La computación paralela es una técnica de programación en la que muchas
instrucci...
1 - ¿Y eso queéloqueé?
La Ley de Moore expresa
que aproximadamente
cada 18 meses (*) se
duplica el número de
transistores ...
1 - ¿Y eso queéloqueé?
• La ley de Moore ha muerto:
– Tecnología actual 32 nanómetros
– Límite 18 nanómetros (cambios)
– S...
2 – Un poco de historia
¿Alguien recuerda los CRAY?
1976: Es uno de los supercomputadores más
conocidos y exitosos de la h...
2 – Un poco de historia
¿Y a Deep Blue?
1997: El primer ordenador en batir
a un gran maestro (Garry Kasparov)
10
2 – Algunos conceptos
Procesos & Threads en un sistema operativo
11
Un proceso proporciona los recursos
necesarios para ej...
2 – Algunos conceptos
Procesos & Threads en un sistema operativo
12
Un thread es la entidad dentro de un
proceso que realm...
3 - ¿Multithreading vs. Parallism?
• Tipos de Multitarea:
– Cooperativa o No Preemptiva (Windows anteriores a
Win95/WinNT ...
3 - ¿Multithreading vs. Parallism?
• Multithreading:
– Técnica que consiste en manejar varios threads en una aplicación:
–...
3 - ¿Multithreading vs. Parallism?
15
Escenario nº1
Escenario nº2
3 - ¿Multithreading vs. Parallism?
Una aplicación puede incrementar el número de threads
para producir la sensación de que...
3 - ¿Multithreading vs. Parallism?
• Conclusión: Se parece pero no es lo mismo
• Podemos tener multithreading en una
estac...
3 - ¿Multithreading vs. Parallism?
• Esto SI es paralelismo 
18
3 - ¿Multithreading vs. Parallism?
• Y más vale que nos preparemos:
19
4 - Paralelismo en .NET 4.0
Microsoft Task Parallel Library (TPL)
20
4 - Paralelismo en .NET 4.0
LINQ - PLINQ
• Proporciona
extensiones
del lenguaje
para poder
utilizar
paralelismo en
nuestra...
LINQ
4 - Paralelismo en .NET 4.0
PLINQ
22
Devuelve colecciones IEnumerable<T> / IQueryable<T>
Devuelve colecciones Paralle...
PLINQ
4 - Paralelismo en .NET 4.0
AsParallel();
AsOrdered();
ForAll(action);
WithDegreeOfParallelism(ncores);
WithCancella...
Demo 1 {PLINQ}
• Partimos de una sencilla consulta LINQ, que
calcula los números primos hasta 10.000.000
• El objetivo es ...
Demo 1 {PLINQ}
public static bool IsPrime(int candidate)
{
if (candidate == 1) return true;
if ((candidate & 1) == 0)
{
if...
private void getPrimesLINQ()
{
int[] array = Enumerable.Range(1, 10000000).ToArray();
clock.Restart();
int[] primesLINQ =
...
private void getPrimesPLINQ()
{
int[] array = Enumerable.Range(1, 10000000).ToArray();
clock.Restart();
int[] primesLINQ =...
private void getPrimesPLINQ()
{
int[] array = Enumerable.Range(1, 10000000).ToArray();
clock.Restart();
int[] primesLINQ =...
private void getPrimesPLINQ()
{
int[] array = Enumerable.Range(1, 10000000).ToArray();
clock.Restart();
int[] primesLINQ =...
Demo 1 online
{PLINQ}
30
Demo 2 {PLINQ}
• Recorrer el árbol de directorios del sitio y
mostrar información de cada fichero.
• Uso de ForAll para ap...
Demo 2 {PLINQ}
private void printInfo(string filename)
{
FileInfo f = new FileInfo(filename);
byte[] bytes = File.ReadAllB...
Demo 2 {PLINQ}
private void getFilesForEach()
{
filesinfoListBox.Items.Clear();
clock.Restart();
var files = Directory.Enu...
Demo 2 {PLINQ}
private void getFilesParallelForAll()
{
filesinfoListBox.Items.Clear();
clock.Restart();
var files = Direct...
Demo 2 online
{PLINQ}
35
4 - Paralelismo en .NET 4.0
Parallel.For
Parallel.ForEach
Parallel.Invoke
Parallel
36
Ejemplo en
la demo nº5
Extensiones p...
Demo 3 {Parallel}
• Calcular los n primeros números de
la serie de Fibbonacci.
• Veremos como usar la versión paralela del...
Demo 3 {Parallel}
static int Fibonacci(int x)
{
if (x <= 1) return 1;
return
Fibonacci(x - 1) +
Fibonacci(x - 2);
}
38
Demo 3 {Parallel}
private void calculateFibonacciFor()
{
clock.Restart();
fibonacciListBox.Items.Clear();
for (int i = 1; ...
Demo 3 {Parallel}
private void calculateFibonacciParallelFor()
{
clock.Restart();
fibonacciListBox.Items.Clear();
Parallel...
Demo 3 online
{Parallel}
41
Demo 4 {Parallel}
• Crear un pequeño cliente de RSS para obtener los
feeds de algunos blogs mediante LINQ2XML.
• Veremos c...
Demo 4 {Parallel}
public class FeedDefinition
{
public string Name { get; set; }
public string Url { get; set; }
public Da...
Demo 4 {Parallel}
List<string> urls = new List<string>();
private void addUrls()
{
urls.Clear();
urls.Add("http://weblogs....
Demo 4 {Parallel}
public List<FeedDefinition> loadFeeds(string path)
{
try
{
XDocument feedxml = XDocument.Load(path);
var...
Demo 4 {Parallel}
private void getFeedsForEach()
{
clock.Restart();
addUrls();
List<FeedDefinition> allfeeds =
new List<Fe...
Demo 4 {Parallel}
private void getFeedsParallelForEach()
{
clock.Restart();
addUrls();
List<FeedDefinition> allfeeds =
new...
Demo 4 online
{Parallel}
48
Demo 5 {TASK class}
• Ejecutar tareas implícitamente (Invoke):
public void InvokeSample()
{
Parallel.Invoke(() => {
Consol...
Demo 5 {TASK class}
• Ejecutar tareas explícitamente (Task class):
Task t1 = Task.Factory.StartNew(() => DoSomething());
5...
Demo 5 {TASK class}
• Encadenar tareas (ContinueWith):
static void SimpleContinuation()
{
string path = @"C:userspublicTPL...
Demo 5 {Task}
• Usar la clase Task para ejecutar varias tareas
en paralelo.
• Aplicar filtros a imágenes (1024x768 ~ 1Mb)
...
Demo 5 {TASK class}
private void ApplyFiltersSequentially()
{
clock.Restart();
ApplyFilterImage1();
ApplyFilterImage2();
A...
private void ApplyFiltersParallel()
{
clock.Restart();
Task t1 = Task.Factory.StartNew(() => ApplyFilterImage1());
Task t2...
Demo 5 {TASK class}
private void ApplyFilterImage1()
{
Bitmap b = (Bitmap)System.Drawing.Image.FromFile(
Server.MapPath("~...
Demo 5 online
{TASK class}
56
Demo 6 {Thread.Priority}
57
• Pregunta: ¿Es posible establecer la prioridad
de un thread en tiempo de ejecución?
• Respues...
Demo 6 {Thread.Priority}
58
public long StartCount(ThreadPriority threadpriority)
{
Thread.CurrentThread.Priority = thread...
Demo 6 {Thread.Priority}
59
ThreadPriority rabbitPriority =
(ThreadPriority)DropDownList1.SelectedIndex;
ThreadPriority tu...
Demo 6 online
{Thread.Priority}
60
Demo 7 {Concurrence}
61
• En un entorno concurrente es bastante
probable encontrarse con situaciones de
bloqueos, o de ele...
Demo 7 {Concurrence}
62
• Mostrar un ejemplo (exagerado!) de cómo en
un entorno multithread, los elementos de una
colecció...
Demo 7 {Concurrence}
63
Dictionary<int, Point> points1 = new Dictionary<int, Point>();
ConcurrentDictionary<int, Point> po...
Demo 7 {Concurrence}
64
Lanzamos dos tareas en paralelo, la primera intenta
modificar un elemento del diccionario (5), mie...
Demo 7 {Concurrence}
65
private void UpdateDictionary()
{
if (points1.ContainsKey(5))
{
Thread.Sleep(2000);
try
{
Point p ...
Demo 7 {Concurrence}
66
private void UpdateConcurrentDictionary()
{
Point oldp = points2[5];
Point newp = new Point(666, 6...
Demo 7 online
{Concurrence}
67
Demo 7 {Concurrence}
68
Thread-safe Collections in .NET Framework 4
and Their Performance Characteristics
That’s all folks!
Dubtes? Dudas? Doubts?
Lluís Franco
lfranco@ordeeno.com
69
Upcoming SlideShare
Loading in …5
×

News40 Parallel Computing

1,380 views
1,288 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,380
On SlideShare
0
From Embeds
0
Number of Embeds
274
Actions
Shares
0
Downloads
23
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

News40 Parallel Computing

  1. 1. Parallel Computing with .NET 4.0 Sacando partido al multi-core Lluís Franco - AndorraDotNet
  2. 2. Agenda 1. Programación paralela ¿Queéloqueé? 2. Un poco de historia y algunos conceptos. 3. ¿Multithreading versus Parallel? 4. Paralelismo en .NET 4.0 (PLINQ, Parallel, Task) 5. Demos… 6. Demos…… 7. Y si… más demos  2
  3. 3. Let’s play! Parallel Computing with .NET 4.0 3
  4. 4. 1 - ¿Y eso queéloqueé? ¿Esto? 4
  5. 5. 1 - ¿Y eso queéloqueé? ¿Acaso esto? 5
  6. 6. 1 - ¿Y eso queéloqueé? Wikipedia dixit: “La computación paralela es una técnica de programación en la que muchas instrucciones se ejecutan simultáneamente. Se basa en el principio de que los problemas grandes se pueden dividir en partes más pequeñas que pueden resolverse de forma concurrente”. “Existen varios tipos de computación paralela: paralelismo a nivel de bit, paralelismo a nivel de instrucción, paralelismo de datos y paralelismo de tareas”. “Durante muchos años, la computación paralela se ha aplicado en la computación de altas prestaciones, pero el interés en ella ha aumentado en los últimos años debido a las restricciones físicas que impiden el escalado en frecuencia”. 6
  7. 7. 1 - ¿Y eso queéloqueé? La Ley de Moore expresa que aproximadamente cada 18 meses (*) se duplica el número de transistores en un circuito integrado. Se trata de una ley empírica, formulada por el co-fundador de Intel, Gordon E. Moore el 19 de abril de 1965, cuyo cumplimiento se ha podido constatar hasta hoy. Ley de Moore: (*) 2 años (1975). 7
  8. 8. 1 - ¿Y eso queéloqueé? • La ley de Moore ha muerto: – Tecnología actual 32 nanómetros – Límite 18 nanómetros (cambios) – Se alcanzará aprox. en 2014 • Solución: – Más núcleos – Computación en paralelo – INTEL / AMD / NVIDIA (CUDA) «La materia presenta efectos cuánticos que harían necesaria una tecnología diferente para seguir realizando cálculos a ese nivel». Stephen Hawking 8
  9. 9. 2 – Un poco de historia ¿Alguien recuerda los CRAY? 1976: Es uno de los supercomputadores más conocidos y exitosos de la historia, y de los más potentes en su época 9
  10. 10. 2 – Un poco de historia ¿Y a Deep Blue? 1997: El primer ordenador en batir a un gran maestro (Garry Kasparov) 10
  11. 11. 2 – Algunos conceptos Procesos & Threads en un sistema operativo 11 Un proceso proporciona los recursos necesarios para ejecutar un programa. Contiene un espacio de memoria virtual, código ejecutable, un contexto de seguridad, un identificador de proceso único, variables de entorno, y al menos un thread de ejecución. Cada proceso se inicia con un único thread, a menudo llamado thread principal, pero puede crear threads adicionales.
  12. 12. 2 – Algunos conceptos Procesos & Threads en un sistema operativo 12 Un thread es la entidad dentro de un proceso que realmente ejecuta el código. Todos los threads de un proceso comparten los recursos y memoria virtual. Además, cada thread mantiene controladores de excepciones, una prioridad de programación, almacenamiento local, y un identificador de thread único. A más threads, más tiempo de CPU. Lógico, no?
  13. 13. 3 - ¿Multithreading vs. Parallism? • Tipos de Multitarea: – Cooperativa o No Preemptiva (Windows anteriores a Win95/WinNT y MacOS): Cada proceso se ocupa de pasar el control al siguiente proceso. Un mal diseño de una aplicación y CATACRACK! – Preferente o Preemptiva (Windows Win95 y superiores, el resto de S.O. modernos): El sistema operativo es el encargado de ceder un tiempo a cada thread de cada proceso (time slice). Un mal diseño de una aplicación no implica el derrumbe del S.O. ya que se ejecutan en modo user. 13
  14. 14. 3 - ¿Multithreading vs. Parallism? • Multithreading: – Técnica que consiste en manejar varios threads en una aplicación: – Permite realizar tareas asíncronas al ‘mismo tiempo’ (aunque realmente no es así). – No es trivial (más complejidad, depuración, acceso prohibido a la interfaz de usuario). 14 ThreadStart job = new ThreadStart(HacerAlgo); Thread thread = new Thread(job); thread.Start();
  15. 15. 3 - ¿Multithreading vs. Parallism? 15 Escenario nº1 Escenario nº2
  16. 16. 3 - ¿Multithreading vs. Parallism? Una aplicación puede incrementar el número de threads para producir la sensación de que varios procesos se llevan a cabo al mismo tiempo. Pero sólo es paralelismo REAL si existen varios cores que los ejecuten en paralelo. 16 3 1 1 1 varios cores
  17. 17. 3 - ¿Multithreading vs. Parallism? • Conclusión: Se parece pero no es lo mismo • Podemos tener multithreading en una estación con un solo core, pero sólo podemos tener paralelismo real en una estación multi- core. • Error clásico: Como desarrolladores, utilizar paralelismo en una máquina virtual (con un solo core), y nos pensamos que estamos haciendo paralelismo ->NOR! 17
  18. 18. 3 - ¿Multithreading vs. Parallism? • Esto SI es paralelismo  18
  19. 19. 3 - ¿Multithreading vs. Parallism? • Y más vale que nos preparemos: 19
  20. 20. 4 - Paralelismo en .NET 4.0 Microsoft Task Parallel Library (TPL) 20
  21. 21. 4 - Paralelismo en .NET 4.0 LINQ - PLINQ • Proporciona extensiones del lenguaje para poder utilizar paralelismo en nuestras consultas LINQ. DATA - Parallel • Situaciones en las que se realiza la misma operación al mismo tiempo sobre los elementos de un origen de colección o matriz. TASKS - Task • Una tarea representa una operación asíncrona, se asemeja a la creación de un Thread o un ThreadPool, pero a un nivel más alto de abstracción. Concurrent • Proporcionan mecanismos para compartir colecciones y elementos entre varios hilos de ejecución (Thread-safe). Más sencillo Más complejo 21
  22. 22. LINQ 4 - Paralelismo en .NET 4.0 PLINQ 22 Devuelve colecciones IEnumerable<T> / IQueryable<T> Devuelve colecciones ParallelQuery<T>
  23. 23. PLINQ 4 - Paralelismo en .NET 4.0 AsParallel(); AsOrdered(); ForAll(action); WithDegreeOfParallelism(ncores); WithCancellation(CancellationToken); WithMergeOptions(ParallelMergeOptions); WithExecutionMode(ParallelExecutionMode); ParallelQuery 23
  24. 24. Demo 1 {PLINQ} • Partimos de una sencilla consulta LINQ, que calcula los números primos hasta 10.000.000 • El objetivo es transformar esta consulta en una consulta de ejecución paralela, mediante el uso de PLINQ. • Posteriormente veremos la diferencia de tiempo de ejecución entre ambas. 24
  25. 25. Demo 1 {PLINQ} public static bool IsPrime(int candidate) { if (candidate == 1) return true; if ((candidate & 1) == 0) { if (candidate == 2) return true; else return false; } for (int i = 3; (i * i) <= candidate; i += 2) { if ((candidate % i) == 0) return false; } return candidate != 1; } 25
  26. 26. private void getPrimesLINQ() { int[] array = Enumerable.Range(1, 10000000).ToArray(); clock.Restart(); int[] primesLINQ = (from x in array where IsPrime(x) select x).ToArray(); var list = primesLINQ.Take(100).ToList(); showValues(list); clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n"); } Demo 1 {PLINQ} 26
  27. 27. private void getPrimesPLINQ() { int[] array = Enumerable.Range(1, 10000000).ToArray(); clock.Restart(); int[] primesLINQ = (from x in array.AsParallel() where IsPrime(x) select x).ToArray(); var list = primesLINQ.Take(100).ToList(); showValues(list); clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n"); } Demo 1 {PLINQ} 27
  28. 28. private void getPrimesPLINQ() { int[] array = Enumerable.Range(1, 10000000).ToArray(); clock.Restart(); int[] primesLINQ = (from x in array.AsParallel().AsOrdered() where IsPrime(x) select x).ToArray(); var list = primesLINQ.Take(100).ToList(); showValues(list); clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n"); } Demo 1 {PLINQ} 28
  29. 29. private void getPrimesPLINQ() { int[] array = Enumerable.Range(1, 10000000).ToArray(); clock.Restart(); int[] primesLINQ = (from x in array.AsParallel().AsOrdered() .WithDegreeOfParallelism(numcores)) where IsPrime(x) select x).ToArray(); var list = primesLINQ.Take(100).ToList(); showValues(list); clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n"); } Demo 1 {PLINQ} 29
  30. 30. Demo 1 online {PLINQ} 30
  31. 31. Demo 2 {PLINQ} • Recorrer el árbol de directorios del sitio y mostrar información de cada fichero. • Uso de ForAll para aplicar una acción a todos los elementos devueltos por un objeto de tipo «ParallelQuery». • Usado para sustituir a For / ForEach ParallelQuery<T>.ForAll<T>(Action<T> action); 31
  32. 32. Demo 2 {PLINQ} private void printInfo(string filename) { FileInfo f = new FileInfo(filename); byte[] bytes = File.ReadAllBytes(f.FullName); FileSecurity fs = f.GetAccessControl(); IdentityReference identity = fs.GetOwner(typeof(NTAccount)); IdentityReference group = fs.GetGroup(typeof(NTAccount)); string s = string.Format( "file '{0}' ({1} kb), owner '{2}' ({3}), accesed at '{4}'", f.Name, (f.Length / 1024).ToString("n2"), identity.Value, group.Value, f.LastAccessTime); filesinfoListBox.Items.Add(s); } 32
  33. 33. Demo 2 {PLINQ} private void getFilesForEach() { filesinfoListBox.Items.Clear(); clock.Restart(); var files = Directory.EnumerateFiles( Server.MapPath(""), "*.*", SearchOption.AllDirectories); foreach (string s in files) { printInfo(s); } clock.Stop(); elapsedTimeLabel2.Text = clock. ElapsedMilliseconds.ToString("n2"); } 33
  34. 34. Demo 2 {PLINQ} private void getFilesParallelForAll() { filesinfoListBox.Items.Clear(); clock.Restart(); var files = Directory.EnumerateFiles( Server.MapPath(""), "*.*", SearchOption.AllDirectories).AsParallel(); files.ForAll<string>(p => printInfo(p)); clock.Stop(); elapsedTimeLabel2.Text = clock. ElapsedMilliseconds.ToString("n2"); } 34
  35. 35. Demo 2 online {PLINQ} 35
  36. 36. 4 - Paralelismo en .NET 4.0 Parallel.For Parallel.ForEach Parallel.Invoke Parallel 36 Ejemplo en la demo nº5 Extensiones para el trabajo secuencial sobre datos.
  37. 37. Demo 3 {Parallel} • Calcular los n primeros números de la serie de Fibbonacci. • Veremos como usar la versión paralela del clásico bucle For (Parallel.For) • Compararemos la diferencia de tiempo entre ambas (For vs. Parallel.For). 37
  38. 38. Demo 3 {Parallel} static int Fibonacci(int x) { if (x <= 1) return 1; return Fibonacci(x - 1) + Fibonacci(x - 2); } 38
  39. 39. Demo 3 {Parallel} private void calculateFibonacciFor() { clock.Restart(); fibonacciListBox.Items.Clear(); for (int i = 1; i <= 40; i++) { fibonacciListBox.Items.Add( Fibonacci(i).ToString()); } clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n2"); } 39
  40. 40. Demo 3 {Parallel} private void calculateFibonacciParallelFor() { clock.Restart(); fibonacciListBox.Items.Clear(); Parallel.For(1, 40, i => { fibonacciListBox.Items.Add( Fibonacci(i).ToString()); }); clock.Stop(); elapsedTimeLabel.Text = clock. ElapsedMilliseconds.ToString("n2"); } 40
  41. 41. Demo 3 online {Parallel} 41
  42. 42. Demo 4 {Parallel} • Crear un pequeño cliente de RSS para obtener los feeds de algunos blogs mediante LINQ2XML. • Veremos como usar la versión paralela del clásico bucle ForEach (Parallel.ForEach) • Compararemos la diferencia de tiempo entre ambas (ForEach vs. Parallel.ForEach ). 42
  43. 43. Demo 4 {Parallel} public class FeedDefinition { public string Name { get; set; } public string Url { get; set; } public DateTime Date { get; set; } public int NumComments { get; set; } } 43 Clase para almacenar información de cada uno de los posts:
  44. 44. Demo 4 {Parallel} List<string> urls = new List<string>(); private void addUrls() { urls.Clear(); urls.Add("http://weblogs.asp.net/scottgu/rss.aspx"); urls.Add("http://andorradotnet.com/blogs/MainFeed.aspx"); urls.Add("http://geeks.ms/blogs/MainFeed.aspx"); urls.Add("http://feeds2.feedburner.com/CienciaKanija"); } 44
  45. 45. Demo 4 {Parallel} public List<FeedDefinition> loadFeeds(string path) { try { XDocument feedxml = XDocument.Load(path); var feeds = from feed in feedxml.Descendants("item") select new FeedDefinition { Name = feed.Element("title").Value, Url = feed.Element("link").Value, Date = DateTime.Parse( feed.Element("pubDate").Value), NumComments = int.Parse( feed.Element(slashNamespace + "comments").Value) }; return feeds.ToList(); } catch (Exception) return null; } } 45
  46. 46. Demo 4 {Parallel} private void getFeedsForEach() { clock.Restart(); addUrls(); List<FeedDefinition> allfeeds = new List<FeedDefinition>(); foreach (var url in urls) { allfeeds.AddRange(loadFeeds(url)); } showFeeds(allfeeds); clock.Stop(); elapsedTimeLabel2.Text = clock. ElapsedMilliseconds.ToString("n2"); } 46
  47. 47. Demo 4 {Parallel} private void getFeedsParallelForEach() { clock.Restart(); addUrls(); List<FeedDefinition> allfeeds = new List<FeedDefinition>(); Parallel.ForEach(urls, url => { allfeeds.AddRange(loadFeeds(url)); }); showFeeds(allfeeds); clock.Stop(); elapsedTimeLabel2.Text = clock. ElapsedMilliseconds.ToString("n2"); } 47
  48. 48. Demo 4 online {Parallel} 48
  49. 49. Demo 5 {TASK class} • Ejecutar tareas implícitamente (Invoke): public void InvokeSample() { Parallel.Invoke(() => { Console.WriteLine("Begin first task..."); GetLongestWord(words); }, // close first Action () => { Console.WriteLine("Begin second task..."); GetMostCommonWords(words); }, //close second Action () => { Console.WriteLine("Begin third task..."); GetCountForWord(words, "species"); } //close third Action ); //close parallel.invoke } 49
  50. 50. Demo 5 {TASK class} • Ejecutar tareas explícitamente (Task class): Task t1 = Task.Factory.StartNew(() => DoSomething()); 50 Task t1 = new Task(() => DoSomething()); t1.Start(); var t1 = Task.Factory.StartNew<int>(() => DoSomething()); Task.WaitAny(t1); int i = t1.Result;
  51. 51. Demo 5 {TASK class} • Encadenar tareas (ContinueWith): static void SimpleContinuation() { string path = @"C:userspublicTPLTestFolder"; try { var firstTask = new Task(() => CopyDataIntoTempFolder(path)); var secondTask = firstTask.ContinueWith((t) => CreateSummaryFile(path)); firstTask.Start(); } catch (AggregateException e) { Console.WriteLine(e.Message); } } 51
  52. 52. Demo 5 {Task} • Usar la clase Task para ejecutar varias tareas en paralelo. • Aplicar filtros a imágenes (1024x768 ~ 1Mb) • El código de los filtros usa ‘unsafe’ para ejecutar código con punteros ¿Alguien de VB en la sala ? 52
  53. 53. Demo 5 {TASK class} private void ApplyFiltersSequentially() { clock.Restart(); ApplyFilterImage1(); ApplyFilterImage2(); ApplyFilterImage3(); ApplyFilterImage4(); ApplyFilterImage5(); ApplyFilterImage6(); clock.Stop(); elapsedTimeLabel.Text = clock.ElapsedMilliseconds.ToString("n"); } 53
  54. 54. private void ApplyFiltersParallel() { clock.Restart(); Task t1 = Task.Factory.StartNew(() => ApplyFilterImage1()); Task t2 = Task.Factory.StartNew(() => ApplyFilterImage2()); Task t3 = Task.Factory.StartNew(() => ApplyFilterImage3()); Task t4 = Task.Factory.StartNew(() => ApplyFilterImage4()); Task t5 = Task.Factory.StartNew(() => ApplyFilterImage5()); Task t6 = Task.Factory.StartNew(() => ApplyFilterImage6()); Task.WaitAll(t1, t2, t3, t4, t5, t6); clock.Stop(); elapsedTimeLabel.Text = clock.ElapsedMilliseconds.ToString("n"); } Demo 5 {TASK class} 54
  55. 55. Demo 5 {TASK class} private void ApplyFilterImage1() { Bitmap b = (Bitmap)System.Drawing.Image.FromFile( Server.MapPath("~/Images/Penguins.jpg")); b.Invert().Save(Server.MapPath("~/Images/PenguinsInvert.jpg")); img1.ImageUrl = "~/Images/PenguinsInvert.jpg"; } private void ApplyFilterImage2() { Bitmap b = (Bitmap)System.Drawing.Image.FromFile( Server.MapPath("~/Images/Desert.jpg")); b.Grayscale().Save(Server.MapPath("~/Images/DesertGrayscale.jpg")); img2.ImageUrl = "~/Images/DesertGrayscale.jpg"; } 55
  56. 56. Demo 5 online {TASK class} 56
  57. 57. Demo 6 {Thread.Priority} 57 • Pregunta: ¿Es posible establecer la prioridad de un thread en tiempo de ejecución? • Respuesta: SI en función del entorno, pero en un entorno multicore potente no tiene demasiado sentido, ya que el S.O. siempre se reserva la opción de modificarla. • Aviso: Existen detractores de cambiar la prioridad a nivel de thread: stackoverflow.com , codinghorror.com
  58. 58. Demo 6 {Thread.Priority} 58 public long StartCount(ThreadPriority threadpriority) { Thread.CurrentThread.Priority = threadpriority; long threadCount = 0; while (LoopSwitch) { Thread.Sleep(1); threadCount++; } return threadCount; } public enum ThreadPriority { Lowest = 0, BelowNormal = 1, Normal = 2, AboveNormal = 3, Highest = 4, }
  59. 59. Demo 6 {Thread.Priority} 59 ThreadPriority rabbitPriority = (ThreadPriority)DropDownList1.SelectedIndex; ThreadPriority turtlePriority = (ThreadPriority)DropDownList2.SelectedIndex; Task<long> t1 = Task.Factory.StartNew<long> (() => priorityTest.StartCount(rabbitPriority)); Task<long> t2 = Task.Factory.StartNew<long> (() => priorityTest.StartCount(turtlePriority));
  60. 60. Demo 6 online {Thread.Priority} 60
  61. 61. Demo 7 {Concurrence} 61 • En un entorno concurrente es bastante probable encontrarse con situaciones de bloqueos, o de elementos eliminados por otros threads. • NET 4.0 proviene de un conjunto de colecciones specializadas thread-safe: System.Collections.Concurrent
  62. 62. Demo 7 {Concurrence} 62 • Mostrar un ejemplo (exagerado!) de cómo en un entorno multithread, los elementos de una colección pueden ser modificados o eliminados por otro thread y provocar un error en tiempo de ejecución. • Para prevenir estos errores veremos como usar un ConcurrentDictionary y su método TryUpdate.
  63. 63. Demo 7 {Concurrence} 63 Dictionary<int, Point> points1 = new Dictionary<int, Point>(); ConcurrentDictionary<int, Point> points2 = new ConcurrentDictionary<int, Point>(); private void FillCollection() { points1.Clear(); points2.Clear(); Random r = new Random(DateTime.Today.Millisecond); for (int i = 0; i < 100; i++) { int v = r.Next(1, 25); points1.Add(i, new Point(v, v)); points2.TryAdd(i, new Point(v, v)); } } 1 (20, 5) 2 (11,16) 3 (3,6) 4 (8,2) 5 (19,25)
  64. 64. Demo 7 {Concurrence} 64 Lanzamos dos tareas en paralelo, la primera intenta modificar un elemento del diccionario (5), mientras que la segunda borra todos los elementos del diccionario: protected void Button1_Click( object sender, EventArgs e) { FillCollection(); Task t1 = new Task(() => UpdateDictionary()); t1.Start(); Task t2 = new Task(() => ClearDictionary()); t2.Start(); Task.WaitAll(t1, t2); }
  65. 65. Demo 7 {Concurrence} 65 private void UpdateDictionary() { if (points1.ContainsKey(5)) { Thread.Sleep(2000); try { Point p = points1[5]; //<- ERROR!!! p.X = 666; p.Y = 666; messagesListBox.Items.Insert(0, string.Format("Changed successfully: p.X = {0}", p.X)); } catch (Exception ex) { messagesListBox.Items.Insert(0, string.Format("Error, {0}", ex.Message)); } } }
  66. 66. Demo 7 {Concurrence} 66 private void UpdateConcurrentDictionary() { Point oldp = points2[5]; Point newp = new Point(666, 666); if (points2.TryUpdate(5, newp, oldp)) { messagesListBox.Items.Insert(0, string.Format( "Changed successfully: p.X = {0}", newp.X)); } else { messagesListBox.Items.Insert(0, string.Format("Error, key and value not found!")); } }
  67. 67. Demo 7 online {Concurrence} 67
  68. 68. Demo 7 {Concurrence} 68 Thread-safe Collections in .NET Framework 4 and Their Performance Characteristics
  69. 69. That’s all folks! Dubtes? Dudas? Doubts? Lluís Franco lfranco@ordeeno.com 69

×