Computação de Alto Desempenho (HPC) e Paralelismo
Vamos mudar um pouco de assunto, faz muito tempo que eu só falo de DSL. Vamos falar de HPC e Paralelismo em Aplicações.
Fazem algumas semanas (18 de Junho), nós tivemos um "Encontro de Arquitetos" aonde o Gebara falou sobre Virtualização e eu falei sobre o tema acima (HPC - High Performance Computing). Parte destes slides foram os mesmo usados num webcast que fiz recentemente sobre o mesmo título em 13 de Agosto de 2008.
Na chamada dos trabalhos tinhamos como descrição de cada uma dos temas
14h30 – 16h00: Virtualização
Virtualização é, hoje em dia, um dos temas mais discutidos em tecnologia da informação. Desde a questão de consolidação e otimização de recursos até a nova onda de “Green IT”, o tema virtualização tem se mantido em destaque. Nesta palestra abordaremos as tecnologias de virtualização da plataforma Microsoft (estação, servidores, aplicações e apresentação). Estabelecer as razões para as quais a virtualização é desejada auxiIia no processo de tomada de decisão sobre qual tecnologia pode ou deve ser utilizada.
Palestrante: Fernando Gebara
16h00-16h30: Coffee-break
16h30-18h00: HPC
HPC foi tema de grandes discussões em tecnologia na decado de 80 quando os processadores estavam próximos do seu limite relativo ao processo de fabricação. Na epóca alguns autores e especialistas da área profetizavam que a atual tecnologia não iria durar até o final do século passado ou inicio deste. A evidência de que isto está ocrrendo vem de números da Intel: para um aumento de 20% de clock fornece um aumento de apenas 13% em desempenho mas com um aumento de 73% em consumo de energia. Ao que tudo indica o caminho do multicore é uma realidade, hoje temos processadores com 4 cores e em breve teremos processadores com até 80 processadores numa única pastilha. Nem todos os problemas podem ser resolvidos via virtualização, alguns problemas necessitam fazer uso destes "cores" de forma otimizada ou em paralelo, é aqui que a computação de alto desempenho (HPC) entra. O objetivo desta palestra é resgatar alguns deste princípios e demonstrar o que tem sido feito nos últimos anos para possibilitar o uso desta alta capacidade de processamento para resolver problemas cada vez mais complexos em todos os ramos de atividades e por que o caminho do HPC é inevitável.
Palestrante: Carlos Hulot
Se alguém quiser saber mais sobre o tema de virtualização recomendo visitar o blog do Gebara.
Neste "post"vou comentar e deixar disponível para download os slides e links que utilizei na palestra.
Meu enfoque para a discussão de alto desempenho foi tentar mostrar porque HPC e Parelelismo podem ser uma das próximas ondas de TI para um futuro não muitos distante.
Quem quiser ter acesso aos slides da minha apresentação eles estão disponíveis no SkyDrive no Live em
Eu sintetizo abaixo o que eu abordei e coloco os links para as referencias que fiz durante esta palestra.
Começei perguntando para a audiência (e por incrível que parece tinha mais gente do que eu esperava, sendo este um assunto muito específico e árido) quem acredita que a próxima onde será a de HPC e parelelismo. Muita pouco gente se manifestou de forma a concordar com está minha afirmação-questão, mas era o que eu esperava....
Na sequencia eu fiz uma pequena restrospectiva do que aconteceu no final dos anos 80 início dos 90 quando se imagina que a tecnologia para a fabricação de processadores tinha chegado ou estava próxima de chegar ao seu limite devido as limitações no processo fabril de fotolitografia que é uma das etapas no processo de fabricação dos chips e que sem um melhoria não permitiria criar processadores menores e mais poderosos (mais detalhes sobre o processo de fabricação podem ser visto em Learn how a microprocessor is made e quem quiser saber como é uma fábrica de semicondutores veja em Get interactive inside the chip factory)
Em seguida eu mostrei algumas das evidências econômicas que me leva a crer que desta fez o HPC/Paralelismo estão aqui para ficar.
Achei também importante relembrar alguns conceitos básicos de processamento paralelo e sistemas distribuídos tais como:
- A Lei Amdahl que limita o speed-up, ou seja em outras palavras mesmo colocando mais processadores para cada problema tem uma hora que não resolve mais nada ou seja não há ganho em desempenho (assim sendo o processamento paralelo ou distribuído também tem suas limitações).
- A taxonomia Flynn muito utilizado nos anos 90 para descrever as arquiteturas dos sistemas paralelos/distribuídos.
- Ligado a Lei de Amdahl está o problema da "granularidade" de um problema
- Paralelismo Funcional e de Dados
- Memória Compartilhada e Distribuída
- Técnicas de Modelagem do problema ou decomposição do domínio (do problema) que é muito importante para se encontrar a melhor solução para paralelizar um problema
- A diferença entre Grids e Clusters
Estes temas podem ser fácilmente encontrados na internet buscando pelas palavras chaves dado que são temas acadêmicos de cursos de arquiteturas paralelas e sistemas distribuídos.
Em seguida eu explique por que as empresas de semicondutores entreram nesta de colocar mais de um "core" numa pastilha e cujo o racional estava na chamada, ou seja "um aumento de 20% de clock fornece um aumento de apenas 13% em desempenho mas com um aumento de 73% em consumo de energia" que como podemos ver não é uma relação das mais eficientes, veja também em www.asyncop.com
E para demonstrar que as empresas de semicondutores estão seriamente envolvidas neste conceito de multicore eu mostrei o caso da Intel que já tem um protótipo que coloca 80 cores num único "chip". Os detalhes e o filme podem ser visto em Discover how, Tera-scale computing research vision, e
Mostrado o que o universo do hardware anda preparando tinha que mostrar o que o universo do software anda fazendo. E em se tratando de MS o objetio era mostar o que estamos fazendo para lidar com este no cenário de hardware.
Cenário Scale-Up (Multi-Core)
O primeiro passo é fazer uma distinção entre plataformas distribuídas e platformas multicore, ou seja scale-down e scale-up respecitvamente. E que no caso da Microsoft se resumem Windows HPC e extensões parelelas para o .Net Framework que virão inclusas na versão 4.0 do .Net.
Começei pelos cenários de scale-up (multicore) por acreditar serem de mais fácil "digestão". Aqui eu recomendo baixar o CTP do novo Microsoft Parallel Extensions to .NET Framework 3.5, June 2008 Community Technology Preview
E "brincar"um pouco com as novas "extensões paralelas do .NET" que virão na versão 4.0. Elas estão refletidas em 3 grandes grupos, a saber, PLINQ (Parallel Linq), CDS (Concurrent Data Structures) e TPL (Task Parallel Library). Para quem quiser conhecer mais recomendo visitar links como:
Parallel LINQ
Parallel Extensions Samples Tour
Understanding the Parallel Class
Ou visitar a página da MS sobre o tema de Processamanto Parelelo
O objetivo das "extensões paralelas do .Net" é facilitar a vida do desenvolvedor. uma vez que hoje existem outras técnicas mais complexas que são hoje usadas para o desenvolvimento de aplicações concorrentes.Entre estas temos
- CCR - Concurrency and Coordination Runtime parte do Microsoft Robotics Studio
- Trata de programação assincrona visto que robos são um conjunto de eventos assincronos. Ele lida com os 3 principais problemas em robótica:
- 1. Assincronicidade
- 2. Concorrencia
- 3. Coordenação e Suporte/Tolerância a falhas
Mais detalhes em podem ser encontrados em CCR User Guide e em CCR Programming - Jeffrey Richter and George Chrysanthakopoulos e Concurrency and Coordination Runtime
- Threadpools - Recurso que permite um programa C# realizar processamento concorrente.
Multithreading pode resolver o problema de multi-tarefas e resposta de um sistema, ao permitir separar “processos” ou “tarefas” para trabalharem de forma independente e assincrona, mas ao mesmo tempo introduz outras complexidades tais como o compartilhamento de recursos (exemplo dos filosofos)
Mais detalhes em Threading (C# Programming Guide) e How to- Use a Thread Pool
Parallel LINQ (PLINQ)
A primeira extensão paralela do .NET é o Parallel LINQ ou PLINQ que é uma implementação paralela do LINQ-to-objects que usa paralelismo de dados. POr exemplo tomemos a seguinte exemplo que está contido no CTP (LINQRayTracer)
Evidentemente não é minha intenção explicar o algoritmo de "ray-tracing" - a não ser que alguém me peça :) - mas é algo como uma forma simples de simular os raios de luz que emanam de uma fonte luminosa. A idéia é simular o comportamento de cada raio ou feixe de luz e sua intereção com os objetos a sua volta. Portanto envolve Física (teoria da luz) e logo um conjunto de equações que demandam muitos calculos. Para visualizar o que estamos falando, recomendo olhar no arquivo LINQRayTracer.cs aonde temos
1: internal void RenderParallel(Scene scene)
2: { 3: int[] rgb = new int[screenWidth * screenHeight];
4:
5: var pixelsQuery =
6: from y in Enumerable.Range(0, screenHeight).AsParallel()
7: let recenterY = -(y - (screenHeight / 2.0)) / (2.0 * screenHeight)
8: select from x in Enumerable.Range(0, screenWidth)
9: let recenterX = (x - (screenWidth / 2.0)) / (2.0 * screenWidth)
10: let point =
11: Vector.Norm(Vector.Plus(scene.Camera.Forward,
12: Vector.Plus(Vector.Times(recenterX, scene.Camera.Right),
13: Vector.Times(recenterY, scene.Camera.Up))))
14: let ray = new Ray() { Start = scene.Camera.Pos, Dir = point } 15: let computeTraceRay = (Func<Func<TraceRayArgs, Color>, Func<TraceRayArgs, Color>>)
16: (f => traceRayArgs =>
17: (from isect in
18: from thing in traceRayArgs.Scene.Things
19: select thing.Intersect(traceRayArgs.Ray)
20: where isect != null
21: orderby isect.Dist
22: let d = isect.Ray.Dir
23: let pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start)
24: let normal = isect.Thing.Normal(pos)
25: let reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal))
26: let naturalColors =
27: from light in traceRayArgs.Scene.Lights
28: let ldis = Vector.Minus(light.Pos, pos)
29: let livec = Vector.Norm(ldis)
30: let testRay = new Ray() { Start = pos, Dir = livec } 31: let testIsects = from inter in
32: from thing in traceRayArgs.Scene.Things
33: select thing.Intersect(testRay)
34: where inter != null
35: orderby inter.Dist
36: select inter
37: let testIsect = testIsects.FirstOrDefault()
38: let neatIsect = testIsect == null ? 0 : testIsect.Dist
39: let isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0))
40: where !isInShadow
41: let illum = Vector.Dot(livec, normal)
42: let lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0)
43: let specular = Vector.Dot(livec, Vector.Norm(reflectDir))
44: let scolor = specular > 0
45: ? Color.Times(Math.Pow(specular, isect.Thing.Surface.Roughness),
46: light.Color)
47: : Color.Make(0, 0, 0)
48: select Color.Plus(Color.Times(isect.Thing.Surface.Diffuse(pos), lcolor),
49: Color.Times(isect.Thing.Surface.Specular(pos), scolor))
50: let reflectPos = Vector.Plus(pos, Vector.Times(.001, reflectDir))
51: let reflectColor = traceRayArgs.Depth >= MaxDepth
52: ? Color.Make(.5, .5, .5)
53: : Color.Times(isect.Thing.Surface.Reflect(reflectPos),
54: f(new TraceRayArgs(new Ray()
55: { 56: Start = reflectPos,
57: Dir = reflectDir
58: },
59: traceRayArgs.Scene,
60: traceRayArgs.Depth + 1)))
61: select naturalColors.Aggregate(reflectColor,
62: (color, natColor) => Color.Plus(color, natColor))
63: ).DefaultIfEmpty(Color.Background).First())
64: let traceRay = Y(computeTraceRay)
65: select new { X = x, Y = y, Color = traceRay(new TraceRayArgs(ray, scene, 0)) }; 66:
67: int rowsProcessed = 0;
68: pixelsQuery.ForAll(row =>
69: { 70: foreach (var pixel in row)
71: { 72: rgb[pixel.X + (pixel.Y * screenWidth)] = pixel.Color.ToInt32();
73: }
74: int processed = Interlocked.Increment(ref rowsProcessed);
75: if (processed % rowsPerUpdate == 0 ||
76: processed >= screenHeight) updateImageHandler(rgb);
77: });
78: }
Esta demo possivilmente só vai mostrar resultado positivos se o seu computador tiver mais de 1 "core". No caso do meu notebook ele possuí dois cores.
Execute primeiro sequencialmente e depois em paralelo e veja como os cores são utilizados em ambos os casos. Para isto use Windows Task Manager (ctrl-alt-del) e selecione a aba Performance e dê um duplo click em CPU Usage.
No meu notebook os resultado foram algo como uma melhora de aproximadamente 10 a 30%. Existe grande variação pois tive de usar um software de gravação que intervere com o resultado final.
Task Parallel Library
O segundo exemplo é o mesmo problema de ray-tracing só que agora usando o segundo recurso da extensão paralela do .NET que é o TPL (Task Parallel Library). TPL é implementado em um bilbioteca e não depende da extensão da linguagem.
1: internal void RenderParallel(Scene scene, Int32[] rgb)
2: { 3: Parallel.For(0, screenHeight, y =>
4: { 5: int stride = y * screenWidth;
6: Camera camera = scene.Camera;
7: for (int x = 0; x < screenWidth; x++)
8: { 9: Color color = TraceRay(new Ray(camera.Pos, GetPoint(x, y, camera)), scene, 0);
10: rgb[x + stride] = color.ToInt32();
11: }
12: });
13: }
Como no caso anterior esta demo só tirará vantagem se o seu computador possuir uma CPU com mais de um core. Se observarem, no caso do processamento sequencial os cores da CPU nunca (ou quase nunca) chegam a 100%. Entetanto quando selecionamos o processamento paralelo (via TPL) os cores são usados a 100%. Acima quando eu mencionei "ou quase nunca" é por que, como no caso anterior, o software usado para gravar interfere com o resultado uma vez que ele consome bastante CPU.
Concurrent Data Structures
Neste CTP ainda não temos nenhum material ou bits sobre o CDS. Assim que ele seja incluido eu volto a blogar sobre que estas estruturas de dados paralelos tais como:
Coleções thread-safe (p.e. ConcurrentDictionary<K,V>, ConcurrentQueue<T>, ConcurrentStack<T>,etc. )
Troca (p.e. BlockingCollection<T>, SynchronousQueue<T>, etc.)
e outros, podem fazer.
Velocity
Como existe uma outra iniciativa para trazer desempenho para aplicações achei importante durante o Encontro de Arquitetos falar sobre o Microsoft Project Code Named “Velocity” Community Technology Preview 1 (CTP1). Esta é um tecnologia que permite "fundir" caches de várias aplicações em um cache único, é como um cache compartilhado. Ou seja você pode agora criar um cache virtual "gigante" que atende a várias aplicações. Como os caches são estruturas intermediárias para armazenagem de dados que devem estar muito próximos da aplicação por questões de desempenho, esta iniciativa permite trazer melhorias a aplicações que precisam de muitos dados e não querem fazer acesso a memória ou discos em outro lugar, logo as informações podem ser mantidas no cache. Embora esta seja uma forma de trazer desempenho a estas aplicações e o cache tenha a "cara" de uma grande memória compartilhada, este não é um problema ou solução de computação de alto desempenho (HPC) ou paralela. De qualquer forma achei importante mencionar e mais detalhes podem ser vistos no link acima.
Cenários Scale-Out (HPC)
Por fim acabei mostrando os cenários de scale-out que significam problemas que requerem soluções em plataformas do tipo cluster ou grids. Para isto eu falei da solucão Windows High Performance Computer Server (WHPCS) que nada mais é do que uma evolução do Windows Computer Cluster Server (WCCS).
Neste caso importante modificações foram introduzidas e melhoradas no Job Scheduler do WHPCS. Novas ferramentas internas e de terceiros foram incorporadas ou agregadas a solução. Além disto o WCF (Windows Communication Foundation) foi utilizado para permitir a criação de "brokers" (mediadores/negociadores). Com estes brokers é possível uma aplicação paralela negociar com o broker um aumento da quantidade de nós de processamento necessários.
Uma descrição para completa pode ser encontrada em Windows HPC