• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Parallel Programming no .NET 4.0
 

Parallel Programming no .NET 4.0

on

  • 1,956 views

Apresentação sobre Parallel Programming no .NET 4.0 por Jorge Paulino (MVP), no evento de aniversário da comunidade NetPonto

Apresentação sobre Parallel Programming no .NET 4.0 por Jorge Paulino (MVP), no evento de aniversário da comunidade NetPonto

Statistics

Views

Total Views
1,956
Views on SlideShare
1,956
Embed Views
0

Actions

Likes
0
Downloads
26
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Parallel Programming no .NET 4.0 Parallel Programming no .NET 4.0 Presentation Transcript

    • http://netponto.org
      14ª Reunião Presencial - 18/09/2010
      Parallel Programming no .NET 4.0Jorge Paulino
    • Jorge Paulino
      Programador VW Autoeuropa
      • VB.NET, .NET Framework 2.0, SQL Server, VBA
      • Automação Industrial (Siemens, Allen Bradley e HMI)
      Microsoft Visual Basic MVP 2009, 2010
      Administrador Comunidade Portugal-a-Programar
      Membro de diversas comunidades como: NetPonto, PontoNetPT, MSDN, Experts-Exchange, CodeProject, etc.
      http://vbtuga.blogspot.com
      http://pontonetpt.com/blogs/jpaulino/default.aspx
      http://twitter.com/vbtuga
    • Agenda
      Introdução
      Novidades .NET Framework 4.0
      TaskParallelLibrary (TPL)
      ParallelClass
      Melhorias na ThreadPool
      Tasks & Futures
      Parallel LINQ (PLINQ)
      Data Structures for Coordination (DSC)
      Ferramentas Diagnóstico
    • Introdução – Evolução dos Processadores
      Moore’sLaw
      “The number of transistors incorporated in a chip will approximately double every 24 months.”
      Gordon Moore, Intel Co-founder (1965)
    • Introdução – Evolução dos Processadores
      Moore’sLaw
      “The number of transistors incorporated in a chip will approximately double every 24 months.”
      Gordon Moore, Intel Co-founder (1965)
      “Moore’s Law scaling should easily let us hit the 80-core mark in mainstream processors within the next ten years and quite possibly even less.”
      Justin Rattner, Intel Vice-President and CTO (February 2007)
    • Introdução – Evolução dos Processadores
      Multicores
      Multiplos núcleos idênticos num só processador
      Intel® Xeon® Processor 7000 (8 cores)
      Symmetric Multiprocessors (SMP’s)
      Arquitectura com dois ou mais processadores idênticos ligados a uma só memória principal partilhada
      Pentium 4
      Pentium
      386
      Intel CPU Trends (sources: Intel, Wikipedia, K. Olukotun)
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
      Paralelismo é diferente de multithreading!
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
      Paralelismo é diferente de multithreading!
      SEQUENCIAL
      Processo A
      Core1
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
      Paralelismo é diferente de multithreading!
      SEQUENCIAL
      Processo A
      Core1
      Processo C
      Processo D
      Processo A
      Processo B
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
      Paralelismo é diferente de multithreading!
      SEQUENCIAL
      Processo A
      Core1
      PARALELO
      Core1
      Processo A
      Core2
      Processo B
      Core3
      Processo C
      Core4
      Processo D
    • Introdução – Conceito
      Paralelismo consiste na decomposição de uma tarefa/dados em tarefas mais pequenas para permitir a execução em simultâneo ou em paralelo.
      Paralelismo é diferente de multithreading!
      SEQUENCIAL
      Optimização
      Processo A
      Core1
      PARALELO
      Core1
      Processo A
      Core2
      Processo B
      Core3
      Processo C
      Core4
      Processo D
    • Introdução – Porque usar paralelismo?
      Hardware mudou ( +núcleos, -velocidade)
      Utilizadores são mais exigentes
      Exigências do mercado mudam
      Com as Parallel Extensions é simples e fácil implementar
    • Introdução – Porque usar paralelismo?
      Hardware mudou ( +núcleos, -velocidade)
      Utilizadores são mais exigentes
      Exigências do mercado mudam
      Com as Parallel Extensions é simples e fácil implementar
      “Porque não utilizar apenas Threads ?”
      • Pesadas (1MB memória virtual)
      • Não estão optimizadas para paralelismo rápido
      • Difíceis de controlar/coordenar (parar, cancelar, começar uma a seguir a outra, esperar pelo fim de várias, etc.)
      • Passar informação entre threads é complicado
      • Diagnóstico não é fácil
    • Novidades .NET Framework 4.0
      Parallel Class
      Task Parallel Library (TPL)
      Task Parallelism
    • Novidades .NET Framework 4.0
      Parallel Class
      PLINQ
      Task Parallel Library (TPL)
      Task Parallelism
      Data Structures for Coordination (DSC)
    • Novidades .NET Framework 4.0
      Parallel Class
      PLINQ
      Task Parallel Library (TPL)
      Task Parallelism
      Data Structures for Coordination (DSC)
      CLR ThreadPool
      Threads
    • Novidades .NET Framework 4.0
      Structured Data Parallelism
      Parallel Class
      PLINQ
      Task Parallel Library (TPL)
      Task Parallelism
      Data Structures for Coordination (DSC)
      CLR ThreadPool
      Threads
    • TaskParallelLibrary (TPL)
      Conjunto de API’s disponíveis nos namespacesSystem.Threading e System.Threading.Tasksda .NET Framework 4.0, que tem como objectivo simplificar o processo de paralelismo.
    • TaskParallelLibrary (TPL)
      Conjunto de API’s disponíveis nos namespacesSystem.Threading e System.Threading.Tasksda .NET Framework 4.0, que tem como objectivo simplificar o processo de paralelismo.
      Existem 2 tipos de paralelismo que podemos usar com a TPL:
    • TaskParallelLibrary (TPL)
      Conjunto de API’s disponíveis nos namespacesSystem.Threading e System.Threading.Tasksda .NET Framework 4.0, que tem como objectivo simplificar o processo de paralelismo.
      Existem 2 tipos de paralelismo que podemos usar com a TPL:
      Data Parallelism
      Task Parallelism
      Parallel.For() e Parallel.ForEach()
      Parallel.Invoke() e Factory.Task()
    • TaskParallelLibrary (TPL) – Data Parallelism
      Parallel.For (fromInclusive, toExclusive, delegate)
      ' Cicloparalelo
      Parallel.For(0, 100, Sub(x) Process(x))
      // Cicloparalelo
      Parallel.For(0, 100, x => Process (x));
      VB.NET
      C#
      VB.NET
      C#
      ' Ciclosequencial
      For Each item InitemCollection
      Process(item)
      Next
      // Ciclosequencial
      foreach(varitem initemCollection)
      {
      Process(item);
      }
      ' Ciclosequencial
      For x As Integer = 0 To 100
      Process(x)
      Next
      // Ciclosequencial
      for (int x = 0; x < 100;x++)
      {
      Process(x);
      }
      Parallel.ForEach(item, source, delegate)
      ' Cicloparalelo
      Parallel.ForEach(itemCollection, Sub(item) Process(item))
      // Cicloparalelo
      Parallel.ForEach(itemCollection, item => Process(item));
    • Task Parallel Library (TPL) – Data Parallelism
      • Escalabilidade
      • Particionamento dinâmico ou manual
      • Métodos para parar, cancelar, sair, etc. (12/20 overloads)
      Não há no entanto garantias da ordem de execução!
      TaskParallelLibrary (TPL) - Task Parallelism
      Parallel.Invoke(…)
      VB.NET
      C#
      Parallel.Invoke(Action1, Action2, …)
      OU
      ‘ Usando um Action Delegate
      Dim actions As Action() = {AddressOfAction1,
      AddressOfAction2}
      Parallel.Invoke(actions)
      Parallel.Invoke(Action1, Action2, ...);
      OU
      // Usando um Action Delegate
      Action[] actions = newAction[] {Action1,
      Action2};
      Parallel.Invoke(actions);
    • Parallel.For(), Parallel.ForEach() e Parallel.Invoke()ParallelFor_ConsoleApplication(VB.NET) ParallelInvoke_ConsoleApplication (C#)RayTracer (VB.NET)
      demonstração
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkerThread 1
      WorkerThread 2

      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkerThread 1
      WorkerThread 2

      WorkItem 1
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem 1
      WorkerThread 1
      WorkerThread 2

      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem 1
      WorkItem2
      WorkerThread 1
      WorkerThread 2

      WorkItem 3
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem2
      WorkerThread 1
      WorkerThread 2

      WorkItem 3
      WorkItem 1
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkerThread 1
      WorkerThread 2

      WorkItem 3
      WorkItem 1
      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem3
      WorkerThread 1
      WorkerThread 2

      WorkItem4
      WorkItem 1
      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem3
      WorkItem4
      WorkerThread 1
      WorkerThread 2

      WorkItem5
      WorkItem 1
      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem3
      WorkItem4
      WorkerThread 1
      WorkerThread 2

      WorkItem5
      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem4
      WorkItem5
      WorkerThread 1
      WorkerThread 2

      WorkItem3
      WorkItem2
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem4
      WorkItem5
      WorkerThread 1
      WorkerThread 2

      WorkItem3
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem 5
      WorkerThread 1
      WorkerThread 2

      WorkItem3
      WorkItem4
      Program
      Thread
    • ThreadPool - .NET Framework 3.5
      Esquema geral de funcionamento
      Global
      Queue
      WorkItem 5
      WorkItem6
      WorkerThread 1
      WorkerThread 2

      WorkItem3
      WorkItem4
      Program
      Thread
      Overheads
      Todas as threads a aceder à Global Queue
      Problemas de sincronização/locks
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      WorkerThread 1
      WorkerThread 2

      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      WorkerThread 1
      WorkerThread 2

      Program
      Thread
      Task 2
      Task 1
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      Task 1
      WorkerThread 1
      WorkerThread 2

      Program
      Thread
      Task 2
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      Task 1
      WorkerThread 1
      WorkerThread 2
      Task 2

      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      WorkerThread 1
      WorkerThread 2
      Task 2

      Task 1
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2

      WorkerThread 1
      WorkerThread 2

      Task 2
      Task 1
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 3

      WorkerThread 1
      WorkerThread 2

      Task 2
      Task 1
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 3
      Task 4

      WorkerThread 1
      WorkerThread 2

      Task 2
      Task 1
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Task 3
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4
      Task 5

      WorkerThread 1
      WorkerThread 2

      Task 2
      Task 1
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Task 3
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4
      Task 5

      WorkerThread 1
      WorkerThread 2

      Task 2
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 3
      Task 4

      WorkerThread 1
      WorkerThread 2

      Task 2
      Task 5
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 3
      Task 4

      WorkerThread 1
      WorkerThread 2

      Task 5
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4

      WorkerThread 1
      WorkerThread 2

      Task 5
      Task 3
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4

      WorkerThread 1
      WorkerThread 2

      Task 6
      Task 5
      Task 3
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4
      Task 6

      WorkerThread 1
      WorkerThread 2

      Task 5
      Task 3
      Program
      Thread
    • ThreadPool - .NET Framework 4.0
      Esquema geral de funcionamento com optimizações
      Global
      Queue
      (lock free)
      Local Queue 1
      Local Queue 2
      Task 4
      Task 6

      WorkerThread 1
      WorkerThread 2

      Task 5
      Task 3
      Program
      Thread
      Optimização aproximada:
      Dual-core = 2x
      Quad-core = 5x
    • Tasks & Futures
      Task
      Task é uma nova abstracção do .NET Framework 4.0 que representa unidades de trabalho assíncrono
      Future
      Task que retorna algum resultado
      Geridos pelo .NET CLR ParallelExtensions
      Automaticamente distribui as Tasks pelos CPU’s/Cores
      Gere a carga de trabalho
      Construídas sobre ThreadPool com gestão automática
    • Tasks e FuturesTask1_ConsoleApplication (VB.NET)Task2_WindowsFormsApplication (C#)
      demonstração
    • Tasks & Futures
      São uma forma simples de efectuar paralelismo e permitem, ao contrário das ThreadPools.QueueUserWorkItem(), controlar o fluxo das threads e efectuar inúmeras acções como:
      • Esperar
      • Cancelar
      • Continuar
      • Combinar
      • Relações (Parent – Child)
      • ControlarFluxo
      • Tratamento de Erros (Exceptions)
      • Debug
    • Parallel LINQ (PLINQ)
      Executa queries LINQ (LINQ to Objects) efectuando os cálculos em paraleloe está disponível no namespaceSystem.Linq.Parallel
      • É declarativa (diz o que quer e não como quer)
      • Suporta todos os .NET Standard QueryOperators
      • Disponível para qualquer IEnumerable<T>
    • Parallel LINQ (PLINQ)
      Executa queries LINQ (LINQ to Objects) efectuando os cálculos em paraleloe está disponível no namespaceSystem.Linq.Parallel
      • É declarativa (diz o que quer e não como quer)
      • Suporta todos os .NET Standard QueryOperators
      • Disponível para qualquer IEnumerable<T>
    • Parallel LINQ (PLINQ)
      Executa queries LINQ (LINQ to Objects) efectuando os cálculos em paraleloe está disponível no namespaceSystem.Linq.Parallel
      • É declarativa (diz o que quer e não como quer)
      • Suporta todos os .NET Standard QueryOperators
      • Disponível para qualquer IEnumerable<T>
      .AsOrdered()
      Preserva a ordem inicial da sequência de à entrada
    • Parallel LINQ (PLINQ)
      Executa queries LINQ (LINQ to Objects) efectuando os cálculos em paraleloe está disponível no namespaceSystem.Linq.Parallel
      • É declarativa (diz o que quer e não como quer)
      • Suporta todos os .NET Standard QueryOperators
      • Disponível para qualquer IEnumerable<T>
      .AsOrdered()
      Preserva a ordem inicial da sequência de à entrada
      .OrderBy()
      Faz o sort à saida
    • Parallel LINQ (PLINQ)
      ParallelEnumerable Operators
      • AsParallel, AsSequential, AsOrdered, AsUnordered
      • WithCancellation, WithDegreeOfParallelism, WithExecutionMode, WithMergeOptions
      MétodoForAll()
    • PLINQPLINQ (VB.NET)BabyNames(C#)
      demonstração
    • Coordination Data Structures
      Concurrent collections
      Synchronization Primitives
      • BlockingCollection<T>
      • ConcurrentBag<T>
      • ConcurrentDictionary<TKey,TValue>
      • ConcurrentQueue<T>
      • ConcurrentStack<T>
      • IProducerConsumerCollection<T>
      • Partitioner, Partitioner<T>, OrderablePartitioner<T>
      • Barrier
      • CountdownEvent
      • ManualResetEventSlim
      • SemaphoreSlim
      • SpinLock, SpinWait
      Exception Handling
      • AggregateException
      Cancellation Primitives
      Initialization Primitives
      • CancellationToken
      • CancellationTokenSource
      • Lazy<T>, LazyInitializer
      • ThreadLocal<T>
    • CancellationModel
      Modelo unificado para cancelamento corporativo através de um CancellationToken e CancellationTokenSource
      VB.NET
      C#
      ‘ Declaração do Token
      DimctsAs New CancellationTokenSource
      DimctAsCancellationToken = cts.Token
      // Declaração do Token
      varcts = newCancellationTokenSource();
      CancellationTokenct = cts.Token;
      ‘ Ordemparacancelar
      cts.Cancel()
      // Ordem para cancelar
      cts.Cancel();
      ‘ Verifica se existe ordem de cancelamento
      If cts.IsCancellationRequestedThen
      ‘ Cancela execução
      EndIf
      // Verifica se existe ordem de cancelamento
      if(cts.IsCancellationRequested)
      {
      // Cancela execução
      }
      Existe ainda uma exception - OperationCanceledException
    • CancellationTokenSourceCancellationToken_WpfApplication (C#) ParallelFor_ConsoleApplication (VB.NET)
      demonstração
    • AggregateException
      Representa um ou mais erros que ocorrem durante a execução da aplicação
    • AggregateExceptionAggregateException (VB.NET)
      demonstração
    • CountdownEvent, Barrier, PartitionerCoordinationDataStructures_ConsoleApplication (C#)ParallelFor_ConsoleApplication (VB.NET)
      demonstração
    • Ferramentas de Diagnóstico
      Parallel Tasks Window
      Listatodas as tasks/threads queestãoactivas e o seuestado
    • Ferramentas de Diagnóstico
      Parallel Tasks Window
      Listatodas as tasks/threads queestãoactivas e o seuestado
      Parallel Stacks Window
      Mostra as tasks/threads activas e as suasdependências
    • Ferramentas de Diagnóstico
      Performance Analysis - Concurrency Visualizer
      Permitir ver como a aplicação interage com ela própria, com o hardware, sistema operativo e outros processos no computador.
    • Ferramentas de Diagnóstico
      Performance Analysis - Concurrency Visualizer
      Permitir ver como a aplicação interage com ela própria, com o hardware, sistema operativo e outros processos no computador.
      CPU UtilizationView
      Visualização da utilização do CPU, indicando a utilização dos cores disponíveis
    • Ferramentas de Diagnóstico
      Performance Analysis - Concurrency Visualizer
      Permitir ver como a aplicação interage com ela própria, com o hardware, sistema operativo e outros processos no computador.
      CPU UtilizationView
      Visualização da utilização do CPU, indicando a utilização dos cores disponíveis
      ThreadsView (Parallel Performance)
      Mostra a evolução de cada thread ao longo da execução, incluindo callstacks(1ms)
    • Ferramentas de Diagnóstico
      Performance Analysis - Concurrency Visualizer
      Permitir ver como a aplicação interage com ela própria, com o hardware, sistema operativo e outros processos no computador.
      CPU UtilizationView
      Visualização da utilização do CPU, indicando a utilização dos cores disponíveis
      ThreadsView (Parallel Performance)
      Mostra a evolução de cada thread ao longo da execução, incluindo callstacks(1ms)
      Cores View
      Mostra a actividade por core, separando as threadsem diferentes cores
    • Parallel Tasks, Parallel Stacks e Performance Analysis Debug_ConsoleApplication (VB.NET)PLINQ (VB.NET)
      demonstração
    • Questões?
    • Referências
      ParallelProgrammingDeveloperCenter
      http://msdn.microsoft.com/en-us/concurrency/default.aspx
      ParallelProgrammingwith Microsoft .NET
      http://parallelpatterns.codeplex.com/
      A Tour Through the Parallel Programming Samples for .NET 4http://blogs.msdn.com/b/pfxteam/archive/2009/12/09/9934811.aspx
      Reactive Extensions (Rx) for .NET 3.5SP1
      http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx
      Using Parallel Extensions for .NET 4 in ASP.NET
      http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx
    • Patrocinadores deste evento
    • Próximas reuniões presenciais
      18/09/2010 - Setembro
      23/10/2010 - Outubro
      20/11/2010 - Novembro
      11/12/2010 - DezembroReserva estes dias na agenda! :)
    • Obrigado!
      Jorge Paulino
      jorgemiguel.paulino@gmail.com
      http://vbtuga.blogspot.com
      http://pontonetpt.com/blogs/jpaulino/default.aspx
      http://twitter.com/vbtuga