Programação Paralela e Concorrente em Haskell - MCTA016-13 -...

79
Programação Paralela e Concorrente em Haskell MCTA016-13 - Paradigmas de Programação Emilio Francesquini [email protected] 2019.Q2 Centro de Matemática, Computação e Cognição Universidade Federal do ABC

Transcript of Programação Paralela e Concorrente em Haskell - MCTA016-13 -...

Page 1: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Programação Paralela e Concorrente emHaskellMCTA016-13 - Paradigmas de Programação

Emilio [email protected]

Centro de Matemática, Computação e CogniçãoUniversidade Federal do ABC

Page 2: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Disclaimer

■ Estes slides foram preparados para o curso de Paradigmasde Programação na UFABC.

■ Este material pode ser usado livremente desde que sejammantidos, além deste aviso, os créditos aos autores einstituições.

■ Conteúdo baseado no texto preparado, e gentilmentecedido, pelo Professor Fabrício Olivetti de França daUFABC.

1

Page 3: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Programação Paralela e Concorrenteem Haskell

Page 4: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Paralelismo vs Concorrência

■ Um programa paralelo é aquele que usa diversos recursoscomputacionais para terminar a tarefa mais rápido.▶ Exemplo: Distribuir os cálculos entre diferentesprocessadores.

2

Page 5: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Paralelismo vs Concorrência

■ Um programa concorrente é uma técnica de estruturaçãoem que existem múltiplos caminhos de controle.

■ Conceitualmente, esses caminhos executam em paralelo,o usuário recebe o resultado de forma intercalada.

■ Se realmente os resultados são processados em paraleloé um detalhe da implementação.

3

Page 6: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Paralelismo vs Concorrência

Imagine uma lanchonete servindo café. Nós podemos ter:

■ Um caixa único e uma fila única→ processamentosequencial

■ Um caixa único e múltiplas filas→ processamentoconcorrente

■ Múltiplos caixas e uma fila→ processamento paralelo■ Múltiplos caixas e múltiplas filas→ processamentoconcorrente e paralelo

4

Page 7: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Paralelismo vs Concorrência

■ Uma outra distinção é que o processamento paralelo estárelacionado com um modelo determinístico decomputação enquanto o processamento concorrente é ummodelo não-determinístico.

■ Os programas concorrentes sempre sãonão-determinísticos pois dependem de agentes externos(banco de dados, conexão http, etc.) para retornar umresultado.

5

Page 8: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Haskell Paralelo

■ No Haskell o paralelismo é feito de forma declarativa e emalto nível.

■ Não é preciso se preocupar com sincronização ecomunicação.

6

Page 9: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Haskell Paralelo - Vantagens

■ Programador não precisa se preocupar com detalhesespecíficos de implementação

■ Funciona em uma diversidade de hardwares paralelos■ Melhorias futuras na biblioteca de paralelismo tem efeitoimediato (ao recompilar) nos programas paralelos atuais

7

Page 10: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Haskell Paralelo - Desvantagens

■ Como os detalhes técnicos estão escondidos, problemasde desempenho são difíceis de detectar

■ Uma vez detectados, os problemas de perfomance sãodifíceis de resolver

8

Page 11: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Haskell Paralelo

■ A única tarefa do programador é a de dividir as tarefas aserem executadas em pequenas partes que podem serprocessadas em paralelo para depois serem combinadasem uma solução final.

■ O resto é trabalho do compilador…

9

Page 12: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Avaliação Preguiçosa

Page 13: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

■ Vamos verificar como a avaliação preguiçosa funciona noHaskell.

■ Para isso utilizaremos a função sprint no ghci que mostrao estado atual da variável.

10

Page 14: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

1 Prelude> :set -XMonomorphismRestriction2 Prelude> x = 5 + 103 Prelude> :sprint x4 x = _

11

Page 15: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

1 Prelude> x = 5 + 102 Prelude> :sprint x3 x = _4 Prelude> x5 156 Prelude> :sprint x7 x = 15

O valor de x é computado apenas quando requisitamos seuvalor!

12

Page 16: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

1 Prelude> x = 1 + 12 Prelude> y = x * 33 Prelude> :sprint x4 x = _5 Prelude> :sprint y6 y = _

13

Page 17: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

1 Prelude> x = 1 + 12 Prelude> y = x * 33 Prelude> :sprint x4 x = _5 Prelude> :sprint y6 y = _7 Prelude> y8 69 Prelude> :sprint x

10 x = 2

A função seq recebe dois parâmetros, avalia o primeiro eretorna o segundo.

14

Page 18: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eu quero agora!

1 Prelude> x = 1 + 12 Prelude> y = 2 * 33 Prelude> :sprint x4 x = _5 Prelude> :sprint y6 y = _7 Prelude> seq x y8 69 Prelude> :sprint x

10 x = 2

15

Page 19: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Quero evitar a fadiga

1 Prelude> let l = map (+1) [1..10] :: [Int]2 Prelude> :sprint l3 l = _4 Prelude> seq l ()5 Prelude> :sprint l6 l = _ : _7 Prelude> length l8 Prelude> :sprint l9 l = [_,_,_,_,_,_,_,_,_,_]

10 Prelude> sum l11 Prelude> :sprint l12 l = [2,3,4,5,6,7,8,9,10,11]

16

Page 20: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exercício 1

O que terá sido avaliado em lista após a execução do seguintecódigo?

1 f x = 2*x2 g x3 | even x = x + 14 | otherwise = f x5

6 lista = [ (x, g x, f x) | x <- [1..], even x ]7 lista' = map snd lista8 sublista = take 4 lista'9

10 print sublista

17

Page 21: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Weak Head Normal Form (WHNF)

Ao fazer:

1 > z = (2, 3)2 > :sprint z3 z = _4 > z `seq` ()5 ()6 > :sprint z7 z = (_,_)

A função seq apenas forçou a avaliação da estrutura de tupla.Essa forma é conhecida como Weak Head Normal Form.

18

Page 22: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Normal Form

Para avaliar uma expressão em sua forma normal, podemosusar a função force da biblioteca Control.DeepSeq:

1 > import Control.DeepSeq2 > z = (2,3)3 > force z4 > :sprint z5 z = (2,3)

19

Page 23: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

Page 24: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

A biblioteca Control.Parallel.Strategies fornece os seguintestipos e funções para criar paralelismo:

1 data Eval a = ...2

3 instance Monad Eval where ...4

5 runEval :: Eval a -> a6

7 rpar :: a -> Eval a8 rseq :: a -> Eval a

20

Page 25: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

■ A função rpar indica que meu argumento pode serexecutado em paralelo.

■ A função rseq diz meu argumento deve ser avaliado e oprograma deve esperar pelo resultado.

■ Em ambos os casos a avaliação é para WHNF. Além disso, oargumento de rpar deve ser uma expressão ainda nãoavaliada, ou nada útil será feito.

21

Page 26: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

■ Finalmente, a função runEval executa uma expressão(em paralelo ou não) e retorna o resultado dessacomputação.

■ Note que o Monad Eval é puro e pode ser utilizado fora defunções com IO.

22

Page 27: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo

Crie um projeto chamado paralelo:

1 stack new paralelo simple2 stack setup

*Slides apenas para replicação em lab.

23

Page 28: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo

■ Edite o arquivo paralelo.cabal e na linhabuild-depends acrescente as bibliotecas parallel,time.

■ Na linha anterior a hs-source-dirs acrescente a linhaghc-options: -threaded -rtsopts-with-rtsopts=-N -eventlog

*Slides apenas para replicação em lab.

24

Page 29: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo

No arquivo Main.hs acrescente:

1 import Control.Parallel.Strategies2 import Control.Exception3 import Data.Time.Clock

*Slides apenas para replicação em lab.

25

Page 30: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

Considere a implementação ingênua de fibonacci:

1 fib :: Integer -> Integer2 fib 0 = 03 fib 1 = 14 fib n = fib (n - 1) + fib (n - 2)

26

Page 31: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

Digamos que queremos obter o resultado de fib 41 e fib40:

1 f = (fib 41, fib 40)

Podemos executar as duas chamadas de fib em paralelo!

27

Page 32: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

1 fparpar :: Eval (Integer, Integer)2 fparpar = do a <- rpar (fib 41)3 b <- rpar (fib 40)4 return (a, b)

28

Page 33: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo

Altere a função main para:

1 main :: IO ()2 main = do3 t0 <- getCurrentTime4 -- evaluate força avaliação para WHNF5 r <- evaluate (runEval fparpar)6 t1 <- getCurrentTime7 print (diffUTCTime t1 t0)8 print r -- vamos esperar o resultado terminar9 t2 <- getCurrentTime

10 print (diffUTCTime t2 t0)

Compile com stack build --profile e execute com:

$ stack exec paralelo --RTS -- +RTS -N1*Slides apenas para replicação em lab. 29

Page 34: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Explicando os parâmetros

■ -threaded: compile com suporte a multithreading■ -eventlog: permite criar um log do uso de threads■ -rtsopts: embute opções no seu programa■ +RTS: flag para indicar opções embutidas■ -Nx: quantas threads usar■ -s: estatísticas de execução■ -ls: gera log para o threadscope

30

Page 35: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

Para o parâmetro N1 a saída da execução retornará:

0.000002s(165580141,102334155)15.691738s

31

Page 36: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Eval Monad

Para o parâmetro N2 a saída da execução retornará:

0.000002s(165580141,102334155)9.996815s

■ Com duas threads o tempo é reduzido pois cada threadcalculou um valor de fibonacci em paralelo.

■ Note que o tempo não se reduziu pela metade pois astarefas são desproporcionais.

32

Page 37: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rpar

■ A estratégia rpar-rpar não aguarda o final dacomputação para liberar a execução de outras tarefas:

Figura 1: rpar-rpar33

Page 38: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rseq

■ Definindo a expressão fparseq e alterando a funçãomain para utilizá-la:

1 fparseq :: Eval (Integer, Integer)2 fparseq = do a <- rpar (fib 41)3 b <- rseq (fib 40)4 return (a,b)

34

Page 39: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rseq

■ Temos como resultado para N2:

5.979055s(165580141,102334155)9.834702s

Agora runEval aguarda a finalização do processamento de bantes de liberar para outros processos.

35

Page 40: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rseq

A estratégia rpar-rseq aguarda a finalização doprocessamento seq:

Figura 2: rpar-rseq 36

Page 41: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rpar-rseq-rseq

Finalmente podemos fazer:

1 fparparseq :: Eval (Integer, Integer)2 fparparseq = do a <- rpar (fib 41)3 b <- rpar (fib 40)4 rseq a5 rseq b6 return (a,b)

37

Page 42: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rpar-rseq-rseq

E o resultado da execução com N2 é:

(165580141,102334155)10.094287s

38

Page 43: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

rpar-rpar-rseq-rseq

■ Agora runEval aguarda o resultado de todos os threadsantes de retornar:

Figura 3: rpar-rpar-rseq-rseq39

Page 44: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Escolhendo a estratégia

■ A escolha da combinação de estratégias depende muitodo algoritmo que está sendo implementado.

■ Se pretendemos gerar mais paralelismo e nãodependemos dos resultados anteriores, rpar-rpar fazsentido como estratégia.

■ Porém, se já geramos todo o paralelismo desejado eprecisamos aguardar o resultadorpar-rpar-rseq-rseq pode ser a melhor estratégia.

40

Page 45: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

Page 46: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

A biblioteca Control.Parallel.Strategies definetambém o tipo:

1 type Strategies a = a -> Eval a

41

Page 47: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

■ A ideia desse tipo é permitir a abstração de estratégias deparalelismo para tipos de dados, seguindo o exemploanterior, poderíamos definir:

1 -- :: (a,b) -> Eval (a,b)2 parPair :: Strategy (a,b)3 parPair (a,b) = do a' <- rpar a4 b' <- rpar b5 return (a',b')

42

Page 48: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

Dessa forma podemos escrever:

1 runEval (parPair (fib 41, fib 40))

Mas seria bom separar a parte sequencial da parte paralelapara uma melhor manutenção do código.

43

Page 49: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

Podemos então definir:

1 using :: a -> Strategy a -> a2 x `using` s = runEval (s x)

44

Page 50: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias de Avaliação

Com isso nosso código se torna:

1 (fib 41, fib 40) `using` parPair

■ Dessa forma, uma vez que meu programa sequencial estáfeito, posso adicionar paralelismo sem me preocupar emquebrar o programa.

45

Page 51: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias parametrizadas

■ A nossa função parPair ainda é restritiva em relação aestratégia adotada, devemos criar outras funçõessimilares para adotar outras estratégias.

■ Uma generalização pode ser escrita como:

1 evalPair :: Strategy a -> Strategy b -> Strategy (a,b)2 evalPair sa sb (a,b) = do a' <- sa a3 b' <- sb b4 return (a',b')

46

Page 52: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias parametrizadas

Nossa função parPair pode ser reescrita como:

1 parPair :: Strategy (a,b)2 parPair = evalPair rpar rpar

47

Page 53: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias parametrizadas

■ Ainda temos uma restrição, pois ou utilizamos rpar ourseq.

■ Além disso ambas avaliam a expressão para a WHNF. Pararesolver esses problemas podemos utilizar as funções:

1 rdeepseq :: NFData a => Strategy a2 rdeepseq x = rseq (force x)3

4 rparWith :: Strategy a -> Strategy a5 rparWith strat = parEval . strat

48

Page 54: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias parametrizadas

Dessa forma podemos fazer:

1 parPair :: Strategy a -> Strategy b -> Strategy (a,b)2 parPair sa sb = evalPair (rparWith sa) (rparWith sb)

49

Page 55: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégias parametrizadas

E podemos garantir uma estratégia paralela que avalia aestrutura por completo:

1 (fib 41, fib 40) `using` parPair rdeepseq rdeepseq

50

Page 56: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégia para listas

Como as listas representam uma estrutura importante noHaskell, a biblioteca já vem com a estratégia parList de talforma que podemos fazer:

1 map f xs `using` parList rseq

51

Page 57: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Estratégia para listas

Essa é justamente a definição de parMap:

1 parMap :: (a -> b) -> [a] -> [b]2 parMap f xs = map f xs `using` parList rseq

52

Page 58: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Page 59: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Vamos definir a seguinte função que calcula a média dosvalores de cada linha de uma matriz:

1 mean :: [[Double]] -> [Double]2 mean xss = map mean' xss `using` parList rseq3 where4 mean' xs = (sum xs) / (fromIntegral $ length xs)

Cada elemento de xss vai ser potencialmente avaliado emparalelo.

53

Page 60: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Compilando e executando esse código com o parâmetro -sobtemos:

Total time 1.381s ( 1.255s elapsed)

O primeiro valor é a soma do tempo de máquina de cadathread, o segundo valor é o tempo total real de execução doprograma.

54

Page 61: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

O que houve?

Total time 1.381s ( 1.255s elapsed)

55

Page 62: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

threadscope

Vamos instalar o programa threadscope para avaliar, faça odownload emhttp://hackage.haskell.org/package/threadscopee:

1 $ tar zxvf threadscope-0.2.10.tar.gz2 $ cd threadscope-0.2.103 $ stack install threadscope

56

Page 63: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

threadscope

Execute o programa da média incluindo o parâmetro -ls efaça:

1 $ threadscope media.eventlog

57

Page 64: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Os gráficos em verde mostram o trabalho feito por cada coredo computador:

Por que um core fez o dobro do trabalho?

58

Page 65: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ No Haskell o paralelismo é feito através da criação desparks,

■ Um spark é uma promessa de algo a ser computado e quepode ser computado em paralelo.

■ Cada elemento da lista gera um spark, esses sparks sãoinseridos em um pool que alimenta os processosparalelos.

59

Page 66: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

Figura 4: https://wiki.haskell.org/ThreadScope_Tour/SparkOverview 60

Page 67: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ Cada elemento que é passado para a função rpar cria umspark e que é inserido no pool.

■ Quando um processo pega esse spark do pool, ele éconvertido em um processo e então é executado.

61

Page 68: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ No momento da criação, antes de criar o spark, éverificado se a expressão não foi avaliada anteriormente.Caso tenha sido, ela vira um dud e aponta para essaavaliação prévia.

62

Page 69: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ Se o pool estiver cheio no momento, ela retorna o statusoverflow e não cria o spark, simplesmente avalia aexpressão no processo principal.

63

Page 70: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ Se no momento de ser retirado do pool ele já tiver sidoavaliado em outro momento, o spark retorna statusfizzled, similar ao dud.

64

Page 71: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

■ Finalmente, se essa expressão nunca for requisitada,então ela é desalocada da memória pelo garbagecollector.

65

Page 72: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Vida de um spark

Sinais de problemas:

■ Poucos sparks→ pode ser paralelizado ainda mais■ Muitos sparks→ paralelizando demais■ Muitos duds e fizzles→ estratégia não otimizada.

66

Page 73: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Voltando ao nosso exemplo, se olharmos para a criação desparks, percebemos que ocorreu overflow (parte vermelha), ouseja, criamos muitos sparks em um tempo muito curto:

67

Page 74: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Vamos tirar a estratégia…

1 mean :: [[Double]] -> [Double]2 mean xss = map mean' xss3 where4 mean' xs = (sum xs) / (fromIntegral $ length xs)

68

Page 75: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

E criar uma nova função que aplica a função mean sequencialem pedaços de nossa matriz:

1 meanPar :: [[Double]] -> [Double]2 meanPar xss = concat medias3 where4 medias = map mean chunks `using` parList rseq5 chunks = chunksOf 1000 xss

Agora criaremos menos sparks, pois cada spark vai cuidar de1000 elementos de xss.

69

Page 76: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

O resultado:

Total time 1.289s ( 1.215s elapsed)

Não tem mais overflow! Mas…70

Page 77: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

A função mean é aplicada em paralelo até encontrar a WHNF,ou seja, apenas a promessa de calcular a média de cada linha!

71

Page 78: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Vamos usar a estratégia rdeepseq.

1 meanPar :: [[Double]] -> [Double]2 meanPar xss = concat medias3 where4 medias = map mean chunks `using` parList rdeepseq5 chunks = chunksOf 1000 xss

72

Page 79: Programação Paralela e Concorrente em Haskell - MCTA016-13 - …professor.ufabc.edu.br/~e.francesquini/2019.q2.paradigm... · 2019. 8. 8. · Exemplo Altereafunçãomainpara: 1

Exemplo: média

Total time 1.303s ( 0.749s elapsed)

😊

73