2020년 5월 8일 금요일

Scala parallel collection foreach return different results

스칼라에서 par.foreach를 썼더니 매번 같은 결과가 나오지 않는다는 것을 알게 되었다.

상황
스칼라를 사용해서 api호출 결과를 통으로 받고 그 결과값들을 하나씩 loop 돌면서 where절 조건에 넣고 group by 집계를 해야하는 이슈가 있었다. 
api 호출 결과가 갈수록 많아지고 집계 데이터의 양이 커지면서 foreach 반복문의 성능이 기하급수적으로 떨어졌다. (대략 2시간가까이 걸렸다.)

조치
처음 조치한 방법은 반복문 조건에 들어갈 내용을 map으로 펼친 후 par.foreach를 돌렸더니 약 30-40분으로 확실히 줄어들었다. 데이터 샘플 몇개만 확인했을 때 이상없어보였다.

문제
하지만 이후 다시 확인해보니 결과가 계속해서 예상치 못한 내용이었고 결론적으로는 이상했다.

원인
찾아보니 병렬 콜렉션을 사용할 경우 스레드들이 atomic하게 처리하지 않는다. 결과적으로 원복했고 이런 실수를 하면 안된다.

예를 들어보자.
var sum =0
(1 to 1000).par.foreach(row => sum+=row)
print(sum)

실행할 때마다 sum의 값이 계속해서 바뀐다.


다음 그림 출처는 Scala for Data Science by Pascal Bugnion 이다.



개인적으로 병렬 콜렉션이 조금은 실망스러운데 저렇게 결과를 내면 어디에 적용이 가능한지 당장 생각나지 않는다. 꼼수를 쓰면 해결가능할텐데 그것도 아닌 것 같다.




댓글 없음:

댓글 쓰기