2013년 1월 10일 목요일

특정 코드를 병렬로 수행하기 - Java

Scala 는 scala.collection.parallel._ 에 ParArray 등 병렬 처리를 지원하는 자료구조가 지원됩니다만, Java 7 까지는 직접적으로 지원하지는 않습니다.

그래서 Java 로 유사하게 Data 처리를 병렬로 수행할 수 있도록 하는 코드를 구현해 봤습니다.

private static int getPartitionSize(int itemCount, int partitionCount) {
    return (itemCount / partitionCount) + ((itemCount % partitionCount) > 0 ? 1 : 0);
}

다음과 같은 절차로 수행됩니다.

  1. ExecutorService 생성 - 논리적 CPU 갯수만큼의 작업스레드를 가지게 한다.
  2. 입력 데이터 컬렉션인 elements 를 Process 갯수로 나눈다. (partitions)
    각 Process 별로 작업할 컬렉션을 분할합니다. ( Process 가 4개이고, elements 수가 100개라면, 0~24 : 0 CPU, 25~49 : 1 CPU ... )
  3. partition 별로 작업을 정의한다. 
  4. 모든 작업을 ExecutorService에게 실행시킨다.
  5. 작업 결과를 취합하여 반환한다.

위의 코드가 아주 제한적인 기능이지만, 입력값 별로 특정 로직을 수행할 때에는 유용합니다. 기본적으로 CPU가 4개라면, 최대 4배까지 빨라집니다. 물론 부가 작업이 있으니 약간은 떨어지겠지요.

만약 집계 기능의 경우는 위의 3, 4 번에서 소계를 수행하는 코드와 마지막 집계하는 코드가 더 필요할 것입니다.

테스트 코드는 다음과 같습니다. 십만번 호출 작업을 하는 테스트 코드 블럭을 100번 반복할 때, CPU 갯수 만큼 나눠서 수행하도록 합니다.


* 소스 중에 컬렉션 관련 메소드는 Google Guava 13.0 을 사용했습니다.

Scala 병렬 프로그래밍

Scala 가 기본적으로 병렬처리를 지원해서 만들어봤습니다.

scala.collection.parallel._ 에 보시면 여러가지 병렬 프로그래밍을 지원하는 자료구조들이 있습니다. 
물론 java 의 ExecutorService를 이용하여 처리할 수 있습니다만, 우아하게 코딩량을 줄여서 처리할 수 있어서 좋습니다.

먼저, void 형 메소드인 ( => Unit) 형태의 메소드 블럭을 주어진 횟수만큼 병렬로 호출하는 코드를  보면, 아주 간단히 ParArray 를 생성하고, map 메소드를 호출하여 지정된 메소드를 수행하도록 합니다.


핵심 코드는 상당히 간단하죠?
그럼 Java 로 비슷한 기능을 만든다면?


차이점이라면 ExecutorService 를 직접 사용하느냐, 내부코드에서 해주느냐의 차이입니다만, scala 의 경우 collection에 filtering, streaming 등 상당히 많은 반복 작업들을 이미 구현해 놓아서, 쓰기도 쉽고, 코드도 간단명료해지네요^^

scala 로 만든 병렬 실행 테스트 코드를 보면,


함수 호출이 아니라 코드 블럭을 정의한 것 같지요?
함수형 언어의 currying 을 이용하여, code block 을 아예 넘길 수 있는 것도 아주 좋은 장점이 되겠습니다.

요즘 Scala의 매력에 푹 빠져있는데, 시간이 나면 Scala 로 Hibernate 와 연계한 base class library 를 만들어야 겠습니다. (case class 를 보면 얼마나 생산성이 좋은지 알 수 있습니다)


2013년 1월 8일 화요일

Scala for C# Programmer

C# 개발자가 Scala 를 쉽게 배울 수 있도록 아주 잘 설명된 블로그가 있어서 소개합니다.

Scala 공식 사이트의  Learn Scala 페이지 중에 있었네요.


If you are a C# programmer, you may find the series "Scala for C# programmers" by Ivan Towlson on flatlander quite helpful:




보시다 시피 C#의 Lambda Expression ,  Extension Methods 등을 알고 있다면, JVM 고유의 특징을 제외하고는 위의 내용을 이해하면 가장 쉽게 Scala 를 배울 수 있겠네요^^

한가지 빠졌다면, case class 에 의한 match 와 @BeanProperty 에 대한 내용은 따로 배워야 할 듯... Field 변수에 대한 getter / setter 는 C# 이 가장 좋은 듯

또 한가지 C#의 메소드 overloading 과 Scala 의 overloading 은 메커니즘이 아주 틀립니다. Scala는 수형검사를 엄밀히 하지 않네요. 이 부분은 API 제작 시 C# 이 더 유리합니다.
다만 사용하는 입장에서는 둘 다 Named Parameter를 지원하므로, 사용하는 방법은 유사합니다.

아, Scala 는 함수형 언어의 특징인 Currying 를 이용하여 여러가지 Signature를 만들 수 있습니다. 이 방식이 더 유연한 방식이라 볼 수 있겠네요.