UFABC - MCZA020-13 - Programação Paralela
Aproximação Trapezoidal em Erlang
Implementação
Baixe o arquivo aqui trap.erl.
Para compilar e rodar faça:
$ erlc trap.erl $ erl -noshell -s trap main A B N P
Onde A
e B
são os valores inicial e final de para \(f(x)\), N
é
o número de trapézios e P
o número de processos.
%% Emilio Francesquini <e.francesquini@ufabc.edu.br> %% 2019-03-21 -module(trap). -export([main/1, go/6, trap/4, trapFold/4]). -mode(native). f(X) -> X * X. %% Solução artificial! É melhor usar um fold. Contudo a solução abaixo %% é bem próxima daquela feita em MPI (veja a solução do livro do PP) trap(Left, Right, TrapCount, BaseLen) -> BaseLen * trap2( Left, Right, TrapCount, BaseLen, (f(Left) + f(Right)) / 2.0, 1). trap2 (Left, Right, TrapCount, BaseLen, Estimate, I) when I < TrapCount -> Estimate2 = Estimate + f(Left + I * BaseLen), trap2 (Left, Right, TrapCount, BaseLen, Estimate2, I + 1); trap2 (_, _, _, _, Estimate, _) -> Estimate. trapFold (Left, Right, TrapCount, BaseLen) -> F = fun (I, Acc) -> Acc + f(Left + I * BaseLen) end, L = lists:seq(1, TrapCount - 1), PartialInt = lists:foldl(F, (f(Left) + f(Right)) / 2.0, L), BaseLen * PartialInt. go (Src, Rank, A, N, H, P) -> LocalN = N div P, LocalA = A + Rank * LocalN * H, LocalB = LocalA + LocalN * H, %% Descomente a linha abaixo para usar a outra implementação %% LocalInt = trap (LocalA, LocalB, LocalN, H), LocalInt = trapFold (LocalA, LocalB, LocalN, H), Src ! [Rank, LocalInt]. getResults (_From) -> %% Pode-se esperar na ordem para garantir resultados sempre iguais %% receive [From, Val] -> receive [_, Val] -> %% Ou em qualquer ordem Val end. main([A, B, N, P]) -> A2 = list_to_float(atom_to_list(A)), B2 = list_to_float(atom_to_list(B)), N2 = list_to_integer(atom_to_list(N)), P2 = list_to_integer(atom_to_list(P)), H = (B2 - A2) / N2, Ranks = lists:seq(0, P2 - 1), [spawn(trap, go, [self(), Rank, A2, N2, H, P2]) || Rank <- Ranks], Int = lists:sum([getResults(Rank) || Rank <- Ranks]), io:fwrite(io_lib:format("~.16f\n", [Int])), init:stop().