2017년 9월 8일 금요일

Zeppelin paragraph 동시 실행

(Zeppelin 0.7.2 사용)

Zeppelin note 에 여러개의 paragraph가 있을 때, 상단의 'Run all paragraphs' 버튼을 누르거나, scheduler를 등록해두면 paragraph들이 하나씩 차례로 실행된다.

그런데 paragraph 들 중 서로 다른 종류의 interpreter들이 섞여 있는 경우는 각 interpreter들이 동시에 실행이 시작된다. 예를 들어 %spark (default), %sql, %sh (shell) 등의 paragraph들이 함께 있는 경우 각 interpreter들 실행이 동시에 실행된다.

따라서 순차적으로 실행시키기 위해서는 트릭이 필요하다.

paragraph 1: %spark
paragraph 2: %sh

이와 같은 경우 동시에 실행되므로, 차례로 paragraph 1 실행이 완료된 후에 paragraph 2 가 실행되게 하려면 paragraph 2를 다음과 같이 %spark 로 변경해주면 된다.

import sys.process._
"command" !!

Zeppelin 이 왜 이렇게 동작하는지 이해가 되지 않는다. 당연히 모든 paragraph 들이 순서대로 실행될 줄 알았는데 그게 아니라서 원하는 결과가 나오지 않았고 원인을 파악하는 데도 한참 걸렸다. 동시 실행, 순차 실행을 제어할 수 있는 옵션이나 함수 같은 것이라도 있으면 좋겠는데 아직은 없는 것 같다.

2017년 8월 18일 금요일

Scala로 Hello World n번 출력

1
def f(n: Int) = print("Hello World\n" * n)


2
non-functional 1
def f(n: Int) = {
  for (i <- 1 to n)
    println("Hello World")
}


3
non-functional 2
def f(n: Int) = {
  for(i <- Iterator.range(0,n))
    println("Hello World");
}


4
recursive
def f(n:Int):Unit = if(n>0) {
  println("Hello World")
  f(n-1)
}


2017년 6월 12일 월요일

spark dynamic allocation

1. dynamic allocation 이란
spark dynamic allocation 기능은 job 실행시 executor 개수를 지정하지 않고 적절한 개수의 executor가 실행되게 하는 기능이다. 하둡 클러스터의 가용 리소스 내에서 최대 성능을 낼 수 있으므로 가능한 사용하는 것이 좋다.

2. dynamic allocation 세팅
dynamic allocation 을 사용하기 위해서는 spark-submit 실행시 옵션 추가만으로 안 될 수도 있다. 하둡 클러스터에 필요한 세팅이 안되어 있으면 job 실행 후 executor가 뜨지 않고 진행율 0%가 계속 유지된다. 클러스터의 각 노드마다 세팅을 변경하고 node manager를 재시작 해주어야 한다.
환경: hadoop 2.5.1, spark 1.6.3(prebuilt for hadoop 2.4)

2-1. spark이 설치 된 곳에서 spark-xxx-yarn-shuffle.jar 파일을 찾아서 각 노드에 복사해준다.
hadoop-2.5.1/share/hadoop/yarn 이런 디렉토리에 복사해 놓으면 classpath로 지정되어 있어서 이 jar 파일을 읽을 수 있다.

2-2. 각 노드에서 yarn-site.xml 파일 편집
<property>
  <name>yarn.nodemanager.aux-services</name>
  <value>spark_shuffle,mapreduce_shuffle</value>
</property>

<property>
  <name>yarn.nodemanager.aux-services.spark_shuffle.class</name>
  <value>org.apache.spark.network.yarn.YarnShuffleService</value>
</property>

위와 같이 편집한다.

2-3. 각 노드에서 node manager 재시작
sbin/yarn-daemon.sh stop nodemanager
sbin/yarn-daemon.sh start nodemanager

stop이 잘 안되면 kill -TERM <pid> 로 종료시키면 된다. 클러스터를 아무도 사용하지 않을 때라면 네임노드에서 전체 nodemanger를 한꺼번에 재시작 할 수도 있다. 공용 클러스터라서 중단없이 운영되기를 원한다면 한꺼번에 재시작 대신 반 정도로 나누어서 두번에 걸쳐 nodemanager를 재시작 해주면 될거다.

3. dynamic allocation 사용
spar-submit 에 --conf spark.shuffle.service.enabled=true --conf spark.dynamicAllocation.enabled=true 두 옵션을 추가하면 사용할 수 있다. 그 밖에 상세 옵션들도 필요하면 쓸 수 있고. 커맨드라인 옵션 대신 spark-defaults.conf 에 추가해서 사용할 수도 있다.


참고

2017년 1월 31일 화요일

특수문자 feff 찾기

텍스트 파일에 특수문자 U+FEFF (Byte Order Mark, BOM)이 포함된 부분을 찾기 위해, grep을 시도했는데 일반적인 방법으로는 잘 매치되지 않는다.

$ cat input.txt | grep -P '\xef\xbb\xbf'

여기저기 찾아보면서 시도해봤는데 위와 같이 하니까 매치된다. vi 에서는 <feff> 이렇게 보이지만, 이 파일은 UTF-8 이라서 실제로는 \xef\xbb\xbf 이렇게 3바이트로 되어있다.

참고: [위키피디아 '바이트 순서 표식']



2017년 1월 16일 월요일

perl에서 계산식을 print할 때 문제


$ perl -e 'print 2**0.5**2'
1.18920711500272

perl 에서 이런 계산식 결과 값을 출력해봤는데 결과가 예상과 다르게 나와서 버그를 발견한 건 아닌가 생각했다. 2의 0.5 승, 즉 sqrt(2)에 다시 2승을 하면 2가 나와야 할 것 같은데 다른 값이 나왔다. perl 버전이 오래된 것이라서 그런가해서 여러 버전의 perl로도 해봤다. 결론부터 말하자면 버그는 아니다. print 사용법과 ** 연산자의 associativity 때문에 발생하는 것이다. +, - 등의 연산자는 left associativity를 가지지만 ** 연산자는 right associativity를 가진다. 그러면 왼쪽 먼저 계산이 되도록 괄호를 쓰면 되는데 그래도 결과가 원하는대로 안나온다. use warnings을 추가해보면 구체적인 이유를 알 수 있다.

$ perl -e 'use warnings; print (2**0.5)**2'
print (...) interpreted as function at -e line 1.
Useless use of exponentiation (**) in void context at -e line 1.
1.4142135623731

print 가 함수로 처리되어서 print(2**0.5) 가 먼저 처리되고 그 결과(void)에 대하여 **2를 하려고 하니 원하는대로 나오지 않는다. warning 메시지가 하나 나오긴 하지만..

$ perl -e 'use warnings; print ((2**0.5)**2)'
print (...) interpreted as function at -e line 1.
2

전체를 감싸는 괄호를 하나 더 추가하니 원하는 결과가 나왔다.

언어 특성상 어쩔 수 없기는 하지만 자칫 실수하기 쉬운 특징인 것 같다. 가능한 print 문 내에 계산식을 쓰지 않고 먼저 계산 값을 변수에 저장해서 그 변수를 출력하도록 하는 것이 좋겠다. 그리고 use warnings를 함께 쓰는 것도 예방하기 좋을 것 같다.(다만 use warnings를 쓰면 실행은 정상적으로 되어도 불필요하게 메시지 출력이 과도해서 출력 메시지를 저장하면 disk full 등의 문제가 발생할 수 있다.)

$ perl -e 'use warnings; $r=(2**0.5)**2; print $r'
2