7가지 동시성 모델 - 3장. 함수형 프로그래밍
TRANSCRIPT
7 가지동시성모델3장 . 함수형프로그래밍
아꿈사스터디 - 정현수
함수형언어의장점
명령형언어
“ ” “ ” 명령형언어는 가변 이면서 공유 되는상태에만 동시성프로그래밍을적용할수있는제약조건이있다
가변상태의위험
❖ 숨겨진가변상태
➢ 현재보이는코드와사용중인 API 의문서를보고서는가변상태여부를파악하기어렵다 .
➢ “ ” 아래코드는그냥보기엔 가변상태 를갖지않기때문에스레드안정성이보장되어보인다 .
그러나 SimpleDateFormat 내부에는가변상태를가지고있다 .
가변상태의위험 (계속 )❖ 탈출한가변상태
➢ 아래코드는 players 리스트는 private 로선언되었고 , synchronized 를통해 addPlayer() 와 getPlayerIterator() 메서드에접근하고있다 .
➢ “아래코드는겉으로는 스레드 - ” 안정성 을보장하는것처럼보인다 .
getPlayerIterator() 의리턴값players.iterator() 가사용되는동안
addPlayer() 를호출한다면문제가발생할수있다 .
즉 , 사용중인 iterator 의원본데이터에 변경이발생하기때문이다 .
(ConcurrentModificationException)
가변상태의위험 (계속 )
함수형프로그래밍이
“ ”동시성 , “ ” 병렬성 에유리한이유
함수형프로그램은 가변상태 가존재하지않는다 .
따라서원천적으로 가변상태의위험에서회피 할수있다 .
명령형프로그램 vs. 함수형프로그램
❖ 주어진수를서로더한값계산
Java
Clojure
명령형프로그램 vs. 함수형프로그램 (계속 )
❖ 주어진수를서로더한값계산
syntax : (reduce func [init val] coll)example :
(reduce + [1 2 3 4 5]) ;;=> 15(reduce + 1 [2 3]) ;;=> 6
명령형프로그램 vs. 함수형프로그램 (계속 )
❖ 주어진수를서로더한값계산
명령형코드에비해간결해졌다 .
주요특징
Lazy Sequence❖ Lazy Sequence
➢ Lazy Evaluation
➢ 계산의결과값이필요할때까지실제계산을늦추는기법 실제필요할때필요한만큼만생성하여작업을수행하여성능향상가능
➢ (take n coll)
■ Collection 에서처음 n 개의아이템만을리턴
➢ (iterate f x)
■ 주어진함수 (f) 를초기값 (x) 에적용시키고 , 다음번순차방문때는함수를그결과에적용하는과정을무한히반복
■ Returns a lazy sequence of x, (f x), (f (f x))....
참조투명성
❖ 참조투명성
➢ 어떤함수가호출 <위치 > 및 <시점 > 에관계없이같은입력값에대해서는항상같은값을
반환
➢ 함수형프로그램은모든함수가참조투명성속성을가진다 .
즉 , 계산순서를바꿀수있기때문에함수코드의병렬화가쉬워진다 .
➢ (+ (+ 1 2) (+ 3 4)) 코드는함수호출순서에관계없이같은결과값을가진다
(+ (+ 1 2) (+ 3 4)) ==> (+ (+ 1 2) 7) ==> (+ 3 7) ==> 10
(+ (+ 1 2) (+ 3 4)) ==> (+ 3 (+ 3 4)) ==> (+ 3 7) ==> 10
데이터흐름
❖ 데이터흐름 (Data Flow) 프로그래밍
➢ 언어의런타임이그래프왼쪽에서시작하여
“ ” 오른쪽으로데이터를 밀어내는방식 으로진행
➢ “ ” 어떤함수와관련된 데이터 가준비되어야
해당함수가실행가능
➢ 각함수는동시에실행가능
➢ Clojure 는 Future 와 Promise ‘ 를통해 데이터
’ 흐름프로그래밍을가능하게한다 . Future 역참조
Clojure 의 Future
❖ Future
➢ 문법 : (future & body)
➢ 코드의몸체를받아다른스레드에서실행 , 실행결과를캐싱하였다가역참조시리턴한다 .
➢ 결과값계산이끝나지않았다면역참조는값이준비될때까지블로킹된다 .
➢ https://clojuredocs.org/clojure.core/future
Clojure 의 Promise❖ Promise
➢ Future 와공통점
■ 값이비동기적으로준비된다
■ 값이리턴되기전까지블로킹된다
■ 역참조가가능하다 : deref or @
➢ Future 와차이점
■ 실행될코드없이도 Promise 를만들수있다
■ deliver 를통해값이설정된다
병렬처리
병렬로처리하기❖ reduce vs. fold
➢ fold
■ clojure.core.reducers 패키지에있는함수
■ - 분할 정복전략 을통해 Parallel 하게수행가능 (reduce 동작을병렬로수행 )
■ syntax : (fold [n] [combinef] reducef coll)
➢ reduce 함수를 fold 함수로변경 : sum 함수를병렬로수행하도록수정
약 2.5 배성능향상
clojure.core.reducers 라이브러리❖ clojure.core.reducers
➢ A library for reduction and parallel folding
➢ 어떻게축소시켜야하는지에대해설명하는일종의조리법
➢ 실제결과를리턴하는대신 , 어떤결과를만들수있는표현을담는조리법을리턴
■ reduce 또는 fold 에전달되기전까지실행되지않는다 .
■ 중간단계의열이만들어질필요가없기때문에더효율적
■ fold 가컬렉션내부에서일어나는모든동작의체인을병렬화하는것을허용
병렬로처리하기❖ map vs. pmap
➢ map : (map f coll)
■ 함수 (f) 와열 (coll) 이주어지면열 (coll) 에담긴각요소에함수 (f) 를적용한결과를담은새로운열을리턴
➢ pmap : (pmap f coll)
■ map 과동일하지만 , 함수 (f) 가병렬로실행
❖ partition-all
➢ 문법 : (partiton-all n) (partition-all n coll) (partiton-all n step coll)
➢ 하나의열 (coll) 을여러개 (n) 의열로묶거나분할한다 .
병렬로처리하기
병렬로처리하기
pmap
partiton-all
병렬로처리하기
map 보다병렬로수행하는 pmap 이더빠르지만전체적인병합횟수가많다 .
partition-all 로일괄처리하면더효율적이다 .