programming erlang ch19 ch20 - andstudy/forge GitHub Wiki
19์ฅ ๋ฉํฐ์ฝ์ด ์๊ณก
๋ณํ์ฑ์ ๋๊ฐ์ง ๋ชจ๋ธ
-
shared state concurrency
- ๋์ผํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ฉด์ ์ฒ๋ฆฌ
- ๋ณํ์๋๋ก ๋์ด์ค๋ฉด์ ์ฌ์๋ฐ์
- ์ ๊ธ ๋งค์ปค๋์ฆ ํ์. ๋ณต์กํด์ง
-
message passing concurrency
- ๊ฐ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ์์. (์์ ํ ์ฐธ์ ์๋์ง๋ง ์ถฉ๋ถํ ์ฐธ์ด๋ผ๊ณ ๊ฐ์กฐ)
- ์ ๊ธ ๋งค์ปค๋์ฆ์ด ํ์์์. ์ฝ๊ณ ๊ฐ๋จ.
20์ฅ ๋ฉํฐ์ฝ์ดCPUํ๋ก๊ทธ๋๋ฐ
๋ฉํฐ์ฝ์ด CPU ์์ ํจ์จ์ ์ผ๋ก ์คํ๋๋ ํ๋ก๊ทธ๋จ ๋ง๋ค๊ธฐ
- ๋ง์ ํ๋ก์ธ์ค๋ฅผ ์ฌ์ฉํ์ธ์
- CPU ๋ ํญ์ ๋นก์ธ๊ฒ ๋๋ ค์ผ ํจ์จ์ .
- side effect ๋ฅผ ํผํด์ฃผ์ธ์
- ๋์์ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐ๋ฉด ์ฌ์๋ฐ์.
- erlang ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต์ ๋ฅผ ์ํด์
- -> ์ฌ์ค 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค๋....
- ์์ฐจ์ ๋ณ๋ชฉ (Sequential bottleneck) ์ ํผํด์ฃผ์ธ์
- ์ฐ๋ฆฌ๋ ๋์ -> ์ด๊ณ -> ์ฃฝ๋๋ค. ์ด๊ฑธ ๋ณ๋ ฌ๋ก ํ ์๋ ์์ด์
ํ๋ก๊ทธ๋จ ๋ณ๋ ฌํ ์ํค๊ธฐ
-
๋ฉ์ธ์ง๋ก data ์ ์ฒ๋ฆฌ๊ฒฐ๊ณผ๋ฅผ ์ฃผ๊ณ ๋ฐ์์ผ๋ก์จ ๋ณ๋ ฌํ
-
map
map(_, []) -> []; map(F, [H|T]) -> [F(H) | map(F,T)]. }}} * pmap ( Parallel map ) : List ์ ์ธ์ ๋ฑ 1๊ฐ์ฉ๋ง ๋ณ๋ ฌ๋ก ํ๊ฐํ์ฌ ์ทจํฉ (์ทจํฉ์์๊ณ ๋ คํจ) {{{#!gcode pmap(F, L) -> S = self(), %% make_ref() returns a unique reference %% we'll match on this later Ref = erlang:make_ref(), Pids = map(fun(I) -> spawn(fun() -> do_f(S, Ref, F, I) end) end, L), %% gather the results gather(Pids, Ref). do_f(Parent, Ref, F, I) -> Parent ! {self(), Ref, (catch F(I))}. gather([Pid|T], Ref) -> receive {Pid, Ref, Ret} -> [Ret|gather(T, Ref)] end; gather([], _) -> []. -
pmap1 : ์ทจํฉ์์๊ณ ๋ คํ์ง ์๋ ๋ฒ์
pmap1(F, L) -> S = self(), Ref = erlang:make_ref(), foreach(fun(I) -> spawn(fun() -> do_f1(S, Ref, F, I) end) end, L), %% gather the results gather1(length(L), Ref, []). do_f1(Parent, Ref, F, I) -> Parent ! {Ref, (catch F(I))}. gather1(0, _, L) -> L; gather1(N, Ref, L) -> receive {Ref, Ret} -> gather1(N-1, Ref, [Ret|L]) end. -
์ธ์ pmap ์ ์ฌ์ฉํ ์ ์๋์?
- ์ฒ๋ฆฌ๋๋ ์์ ๋์ด ์ ์ผ๋ฉด pmap ์ฌ์ฉํ์ง ๋ง์ธ์
- ํ๋ก์ธ์ค๊ฐ ๋๋ฌด ๋ง์ด ์์ฑ๋ ๊ฒฝ์ฐ๋ฅผ ํผํด์ฃผ์ธ์
- ์กฐ๊ธ ๋ ์ถ์ํํด์ ์ฌ์ฉํ์ธ์. ์ทจํฉ์์ ๊ณ ๋ ค
๋ฉ์ธ์ง๋ ์๊ฒ, ๊ณ์ฐ์ ํฌ๊ฒ
-
SMP Erlang (Symmetric Multi Processing)
-
erl -smp +S ์ค์ผ์ฅด๋ฌ๊ฐฏ์N
-
N์ ๋ฐ๋ก ์ค์ ํ์ง ์์ผ๋ฉด ๋จธ์ ์ CPU ๊ฐฏ์๊ฐ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ๋จ.
||Erlang (BEAM) emulator version 5.6.3 {{{#red [smp:2]}}} [async-threads:0]|| ||Eshell V5.6.3 (abort with ^G)|| ||1>||
-
-
-smp ์ต์ ์ ์ด์ฉํ์ฌ ๊ฐ์ ๋ฉํฐ์ฝ์ดCPU ๋ฅผ emulate ํ๊ธฐ์ํ ์คํฌ๋ฆฝํธ
-
runtests.pl
for( $i = 1; $i < 32; $i++ ){ print "$i \n"; # CPU ๊ฐฏ์๋ฅผ 1๋ถํฐ 32๊ฐ๊น์ง ๋๋ ค๊ฐ๋ฉด์ ptests:tests(CPU๊ฐฏ์) ์ํ system("erl -boot start_clean -noshell -smp +S $i -s ptests tests $i >> results.txt"); } set i = 1 FOR /L %%i IN (1,1,5) DO erl -boot start_clean -noshell -smp +S %%i -s ptests tests %%i >> results.txt
-
-
ํ ์คํธ ํ๋ก๊ทธ๋จ
-module(ptests). -export([tests/1, fib/1]). -import(lists, [map/2]). -import(lib_misc, [pmap/2]). tests([N]) -> Nsched = list_to_integer(atom_to_list(N)), run_tests(1, Nsched). run_tests(N, Nsched) -> case test(N) of stop -> init:stop(); Val -> io:format("~p.~n",[{Nsched, Val}]), run_tests(N+1, Nsched) end. test(1) -> %% Make 100 lists %% Each list contains 1000 random integers seed(), S = lists:seq(1,100), L = map(fun(_) -> mkList(1000) end, S), {Time1, S1} = timer:tc(lists, map, [fun lists:sort/1, L]), {Time2, S2} = timer:tc(lib_misc, pmap, [fun lists:sort/1, L]), {sort, Time1, Time2, equal(S1, S2)}; test(2) -> %% L = [27,27,27,..] 100 times L = lists:duplicate(100, 27), {Time1, S1} = timer:tc(lists, map, [fun ptests:fib/1, L]), {Time2, S2} = timer:tc(lib_misc, pmap, [fun ptests:fib/1, L]), {fib, Time1, Time2, equal(S1, S2)}; test(3) -> stop. %% Equal is used to test that map and pmap compute the same thing equal(S,S) -> true; equal(S1,S2) -> {differ, S1, S2}. %% recursive (inefficent) fibonacci fib(0) -> 1; fib(1) -> 1; fib(N) -> fib(N-1) + fib(N-2). %% Reset the random number generator. This is so we %% get the same sequence of random numbers each time we run %% the program seed() -> random:seed(44,55,66). %% Make a list of K random numbers %% Each random number in the range 1..1000000 mkList(K) -> mkList(K, []). mkList(0, L) -> L; mkList(N, L) -> mkList(N-1, [random:uniform(1000000)|L]).
๋ณ๋ ฌํ ์์ 1. mapreduce
-
map + reduce
-
map : mapping ํ๋ก์ธ์ค๊ฐ {Key,Value} ์์ ์คํธ๋ฆผ ์์ฑํด์ reduce ํ๋ก์ธ์ค๋ก ๋ณด๋ด๊ธฐ
-
reduce : reduce ํ๋ก์ธ์ค๋ ๊ฐ์ ํค๋ฅผ ์ง๋ ์๋ผ๋ฆฌ ๊ฒฐํฉํ๋ ๋ฐฉ์์ผ๋ก ๋ณํฉ
-module(phofs). -export([mapreduce/4]). -import(lists, [foreach/2]). %% F1(Pid, X) -> sends {Key,Val} messages to Pid %% F2(Key, [Val], AccIn) -> AccOut mapreduce(F1, F2, Acc0, L) -> S = self(), Pid = spawn(fun() -> reduce(S, F1, F2, Acc0, L) end), receive {Pid, Result} -> Result end. reduce(Parent, F1, F2, Acc0, L) -> process_flag(trap_exit, true), ReducePid = self(), %% Create the Map processes %% One for each element X in L foreach(fun(X) -> spawn_link(fun() -> do_job(ReducePid, F1, X) end) end, L), N = length(L), %% make a dictionary to store the Keys Dict0 = dict:new(), %% Wait for N Map processes to terminate Dict1 = collect_replies(N, Dict0), Acc = dict:fold(F2, Acc0, Dict1), Parent ! {self(), Acc}. %% collect_replies(N, Dict) %% collect and merge {Key, Value} messages from N processes. %% When N processes have terminated return a dictionary %% of {Key, [Value]} pairs collect_replies(0, Dict) -> Dict; collect_replies(N, Dict) -> receive {Key, Val} -> case dict:is_key(Key, Dict) of true -> Dict1 = dict:append(Key, Val, Dict), collect_replies(N, Dict1); false -> Dict1 = dict:store(Key,[Val], Dict), collect_replies(N, Dict1) end; {'EXIT', _, Why} -> collect_replies(N-1, Dict) end. %% Call F(Pid, X) %% F must send {Key, Value} messsages to Pid %% and then terminate do_job(ReducePid, F, X) -> F(ReducePid, X).
-
-
mapreduce ์์
-
map : generate_words -> ํ์ผ์์ word ๋ฅผ ์ฐพ๊ธฐ
-
reduce : count_words -> word ์ ์ฌ์ฉ ๋น๋์
-module(test_mapreduce). -compile(export_all). -import(lists, [reverse/1, sort/1]). test() -> wc_dir("."). wc_dir(Dir) -> F1 = fun generate_words/2, F2 = fun count_words/3, Files = lib_find:files(Dir, "*.erl", false), L1 = phofs:mapreduce(F1, F2, [], Files), reverse(sort(L1)). generate_words(Pid, File) -> F = fun(Word) -> Pid ! {Word, 1} end, lib_misc:foreachWordInFile(File, F). count_words(Key, Vals, A) -> [{length(Vals), Key}|A].
-
๋ณ๋ ฌํ ์์ 2. ๋์คํฌ ์์ธ
- "์ด๊ฒ์ ๋ณต์กํ ํ๋ก๊ทธ๋จ์ ๋๋ค.(์ด ์ฑ ์์ ๊ฐ์ฅ ๋ณต์กํ๋ค.)"
- "๋ชจ๋ ํฉํด ์ฝ๋๊ฐ ์ฝ 1200์ค์ด๋ ๋๋ ๊ด๊ณ๋ก ๋๋ ์ฌ๊ธฐ ๊ทธ ์ฝ๋๋ฅผ ์ ๋ถ ํฌํจ์์ผ ์๋ผ๋๋ ์์น์ ๋ฐ๊ณ ์ถ์ง๋ ์๋ค" by ์กฐ ์์คํธ๋กฑ
๋ฏธ๋๋ก ์ฑ์ฅํ๊ธฐ
- ์ผ๋ญ์ผ๋ก ์๋ก์ด ์คํ์ผ์ ํ๋ก๊ทธ๋จ ๋ง๋ค๊ธฐ๋ฅผ ์ฆ๊ฒจ๋ณด์