2009년 9월 1일 화요일

Test Automation

연구에는 실험이 많이 필요하다.
구체적으로, 내가 하는 H.264 Intra Prediction 연구에는, 특정 알고리즘을 적용했을 때, bitrate와 PSNR이 어떻게 변하는지 실험을 해야 한다.  실험을 어떤 데이터를 대상으로 하는지도 중요한데,

  • 여러 종류의 이미지 : foreman, mobile, parkrun
  • 여러 size의 이미지 : QCIF(172×144), CIF(352×288), 720p(1280×720), 1080p(1920×1080)
  • 여러 QP 값 : 16, 20, 24, 28

등 여러 변화를 줄 수 있다.
더 많은 실험을 할 수록 더 많은 특성을 파악할 수 있는데, 모든 경우에 대해 실험을 하려면 많은 시간이 필요하다.
이럴 때, 실험을 얼마나 자동화하여, 별도의 조작을 하지 않고 실험을 많이 할 수 있는지가 중요하게 된다.
이러한 automation의 중요성을 근래 연구를 하게 되면서 많이 실감했다.
몇 단계를 걸쳐, 수작업으로 하던 것을 어떻게 편리하게 바꿨는지에 대해 설명하겠다.

현재 연구에 추출해야 하는 데이터는 YUV raw data를 encoding한 후 bitrate와 PSNR이다.
본래 H.264 encoder의 reference software인 JM 7.3과, JM 7.3 기반에서 우리가 추가한 사항들의 encoder가 얼마나 성능 차이를 보이는지 확인하고자 한다.
두 가지 version의 encoder로 여러 YUV 파일에 대해 encoding을 한다.
stat.dat 파일에

 ————————————————————–
  This file contains statistics for the last encoded sequence  
 ————————————————————–
 Sequence                     : ../IMAGES/akiyo_cif.yuv
 No.of coded pictures         :  300
 Freq. for encoded bitstream  :   30
 Bitrate(kb/s)                : 4266.30
 Hadamard transform           : Not used
 Image format                 : 352×288
 Error robustness             : Off
 Search range                 : 16
 No of frame used in P pred   : 1
 Entropy coding method        : CAVLC
 Search range restrictions    : none
 RD-optimized mode decision   : not used
 ——————-|—————|—————|
     Item           |     Intra     |   All frames  |
 ——————-|—————|—————|
 SNR Y(dB)          | 47.42         | 47.40         |
 SNR U/V (dB)       | 48.52/49.42   | 48.49/49.37   |
 Average quant      |    16         |  0.00         |

과 같이 결과가 남는데, 우리가 필요로 하는 것은 굵은 글씨로 표시한 bitrate와 PSNR이다.
encoder.cfg 파일에

InputFile             = “./IMAGES/foreman_qcif.yuv”       # Input sequence, YUV 4:2:0,
InputHeaderLength     = 0      # If the inputfile has a header, state it’s length in byte here
FramesToBeEncoded     = 300    # Number of frames to be coded  
SourceWidth           = 176    # Image width in Pels, must be multiple of 16
SourceHeight          = 144    # Image height in Pels, must be multiple of 16

TraceFile             = “trace_enc.txt”
ReconFile             = “test_rec.yuv”
OutputFile            = “test.264″

IntraPeriod           =  1   # Period of I-Frames (0=only first)
QPFirstFrame          = 28  # Quant. param for first frame (intra) (0-51)
QPRemainingFrame      = 28  # Quant. param for remaining frames (0-51)

굵은 글씨로 표시한 값들을 바꿔서, 이미지 size, 종류, 그리고 QP 값을 조정할 수 있다.

1. 수작업

encoder.cfg를 메모장에 띄워서 수정하고, lencod.exe를 돌린다.
encoding이 완료되면, stat.dat에서 필요한 값들을 뽑아서 excel에 입력한다.
QCIF 이미지에 대해서는 encoding이 20초 가량, CIF는 1~2분 가량 걸린다.
오랜 시간 동안 복사-붙여넣기를 해야 하며 그 동안 다른 작업을 못 한다.
불행히도 처음에는 이 방법으로 실험 데이터를 수집하였다;
조금 개선한 것은 stat.dat를 메모장 대신 AcroEdit으로 열어서, 새로 열 필요 없이 F5(새로고침)하였다는 정도?ㅎㅎ
처음 한 번은 할만한데, encoder이 바뀔 때마다 다시 해야 하니 죽을 맛이었다;

2. Perl Script

그러다가 진수 형을 통해 서버에서 script를 돌려서 이 작업을 자동화 할 수 있음을 알게 되었다.
해당 lencod.exe를 Linux에서 재컴파일 후 (다행히 JM이 기본적으로 linux용 makefile도 제공한다)
shell에서 다음 script를 돌리는 것이다:

#!/bin/bash
mkdir STAT

perl -pi -e ’s/FramesToBeEncoded += +[0-9]+/FramesToBeEncoded     = 300/g’ encoder.cfg
perl -pi -e ’s/SourceWidth += +[0-9]+/SourceWidth = 352/g’ encoder.cfg
perl -pi -e ’s/SourceHeight += +[0-9]+/SourceHeight = 288/g’ encoder.cfg

######################## QP = 16 #########################
mkdir STAT/QP16
perl -pi -e ’s/QPFirstFrame += +[0-9]+/QPFirstFrame       = 16/g’ encoder.cfg
perl -pi -e ’s/QPRemainingFrame += +[0-9]+/QPRemainingFrame       = 16/g’ encoder.cfg

perl -pi -e ’s/[a-zA-Z0-9_]+.yuv/foreman_cif.yuv/g’ encoder.cfg
./lencod.exe
cat stat.dat > ./STAT/QP16/stat_foreman.dat
perl -pi -e ’s/[a-zA-Z0-9_]+.yuv/akiyo_cif.yuv/g’ encoder.cfg
./lencod.exe
cat stat.dat > ./STAT/QP16/stat_akiyo.dat
perl -pi -e ’s/[a-zA-Z0-9_]+.yuv/mobile_cif.yuv/g’ encoder.cfg

script가 알아서 encoder.cfg 파일을 수정해 가면서,
생성된 stat.dat 파일을 이름을 바꿔서 분류된 폴더로 복사 해 준다.
이 정도로 자동화 되면, 우선 서버에 작업을 걸어놓고, 완료되면 stat 파일들을 열어서 excel에 입력하면 된다.
하지만 여기에도 stat 파일을 일일이 열어서 excel에 입력해 주는 수고를 해야 한다.

3. Perl Script + Custom Stat

이를 극복하기 위하여 최종적으로 도입한 방법이 CustomStat.txt 파일을 만드는 것이다.
우리가 필요로 하는 stat.dat 결과는 lencod.exe에서 생성하는 것이다.
따라서 lencod C code 내부에 어딘가 stat.dat를 fprintf 해 주는 부분이 있다.
이를 매 encoding마다 별도의 파일에 출력하지 않고, 하나의 파일에 계속 append 하면, 일일이 여러 개 파일을 열어 볼 필요가 없다.
또한 excel에 일일이 입력이 귀찮으므로, excel에서 자동으로 읽을 수 있는 tab으로 분리하면 훨씬 편하다.

다음과 같은 코드를 추가하였다:

   FILE *fp = fopen( “CustomStats.txt”, “a” );

   fprintf( fp, “%s\t%d\t%6.2f\t%5.2f\t%2.3f\t%2.3f\n”,
    input->infile, // Filename
    absm(input->qp0), // QP
    stat->bitrate/1000, // Bitrate
    snr->snr_ya, // PSNR
    fI16Selection, // I16Selection
    fPercentageI16Skipped // EarlyTermination
    );

이와 같은 코드가 추가된 상태에서 Perl script를 수행하면

../IMAGES/parkrun_ter_720p.yuv 16 128794.95 45.65 0.111 58.219
../IMAGES/shields_ter_720p.yuv 16 88204.45 45.82 3.811 55.537
../IMAGES/stockholm_ter_720p.yuv 16 87674.95 45.73 8.589 52.459
../IMAGES/blue_sky_1920×1072.yuv 16 97491.12 47.34 47.846 36.483
../IMAGES/pedestrian_area_1920×1072.yuv 16 86616.49 46.87 17.506 41.591
../IMAGES/rush_hour_1920×1072.yuv 16 75639.1 46.74 26.155 34.994
../IMAGES/tractor_1920×1072.yuv 16 125658.59 46.83 5.165 -49.684
../IMAGES/parkrun_ter_720p.yuv 20 98964.88 41.7 0.158 56.513
../IMAGES/shields_ter_720p.yuv 20 59571.22 42.16 8.863 51.714

와 같이 CustomStat.txt 파일에 결과가 깔끔하게 정리된다.
이는 excel에서 한번에 쉽게 정리되며, 평균치를 바로 알 수 있다.

여기에 추가로, 두 가지 version을 비교하려면, 특정 수식에 데이터를 복사 하는 작업을 거치는데,
이도 하려고 하면, 더 쉽게 자동화 할 수 있을 것이다.
그렇다고 멋진 UI를 갖춘 시스템을 개발해서, 2개 lencod.exe만 지정하면, 모든 이미지에 대해 상세 수치와, 비교 그래프까지 만들어주는 프로그램을 만드는 것은 overkill이니… (사실 이래서 웬만한 영화에 나오는 멋진 UI들은 말이 안 된다;; )
자동화와 수작업, 그리고 실험량의 적절한 조화를 찾는 것이 중요하겠다.

Perl에 대해서 좀 더 공부할 가치가 있을 듯

4 comments June 25th, 2009

Verilog in Source Insight

그 동안 Verilog source 편집을 AcroEdit으로 하다가, 얼마 전에 SourceInsight로 갈아탔다.
SourceInsight는 아피스 다닐 때 효석형으로부터 알게 된 유용한 소스 편집 툴이다.

Windows 환경에서 작업할 때는 보통 소스 편집기와 디버거가 내장된 IDE (MS VC++, Java Netbeans)를 사용하는데,
Unix 환경에서 작업하면 Windows 환경에서 소스를 편집해서 FTP로 Unix로 복사해서 컴파일 및 테스트하는 방법을 사용한다.
원래 vi나 emacs에 능숙하면 Unix에서 바로 작업할 수도 있을텐데, vi나 emacs를 습득하기 위한 learning curve가 나에게 너무 가파르고 (우선 당장 작업해야 하는 경우가 많아서), FTP로 복사하는 것에 큰 불편함을 느끼지 못한다 (지금까지 작업했던 프로젝트의 규모에서는;  물론 메이플스토리 같은 엄청난 규모의 프로젝트는 매번 FTP 복사하기엔 무리가 있을 것이다.ㅎ)
흔히 사람들은 vi나 emacs가 엄청나게 편리하다고 얘기하는데,
AcroEdit 같은 편집기도, macro, replace word 등의 기능을 충분히 지원하고 (이미 그 단축키들을 외우고 있고)
어쨌거나 마우스가 없던 시절을 위해 설계된 vi, emacs가, 마우스를 사용하는 여타 편집기보다 강력할 수 있을지 의문이다.ㅎㅎ

아무튼 본론으로 돌아가서, 위와 같은 이유로 전에는 AcroEdit을 사용했는데, 문득 SourceInsight를 사용하면 더 좋지 않을까 하는 생각이 들었다.  AcroEdit은 프로젝트 개념이 없어서 (다시 보니 있구나.ㅎㅎ 아무튼; ),  매번 관련 source를 일일이 열어야 하는 불편함이 있었다.  그리고 결정적으로 keyword highlight이 되지 않는 것이 가독성을 떨어뜨린다.

본래 SourceInsight도 Verilog 언어를 기본적으로 지원하진 않는다.  대신 language를 추가하는 기능이 있고, 홈페이지에서 Verilog 지원 파일을 제공한다.  하지만 이 파일에 심각한 결함이 있다:

본래 Verilog syntax에서는 위와 같이 선언 후에 oPixel_0, oPixel_1을 이어 쓸 수 있는데, verilog.clf 파일에서는 이를 인식하지 못한다.  각자 선언을 다른 줄에 해 주면 문제 없지만, 이렇게 코드를 작성하는 것은 불편하며, 이미 작성된 코드를 바꾸기도 싫다.
그리고 전체 코드가 다음과 같이 일부 highlight 되지 않는 것도 불편하다:

Source Insight는 custom language를 정의할 수 있는 인터페이스를 제공하고 있으며, verilog.clf도 이를 이용해서 만들어진 것이다.
Custom language의 세부 사항은 Options - Document Options - Language - Properties 에서 확인 가능하다.

여기에서 주요 keyword에 대한 선언 방식이 regular expression으로 정의되어 있는 것을 볼 수 있다.
Source Insight에서 사용하는 regular expression에 대한 설명은 홈페이지에서 제공한다.

컴파일러 수업에서 regular expression을 배웠으므로, Verilog의 올바른 문법에 맞게 고치려는 시도를 해 보았다.

wire\w+\[.*\]\w+\([a-zA-Z][a-zA-Z0-9_]*\)
wire\w+\([a-zA-Z][a-zA-Z0-9_]*\)

wire\w+\[.*\]\w+\([a-zA-Z][a-zA-Z0-9_]*\)\w*,\w*\([a-zA-Z][a-zA-Z0-9_]*\)
wire\w+\[.*\]\w+\([a-zA-Z][a-zA-Z0-9_]*\)(\w*,\w*\([a-zA-Z][a-zA-Z0-9_]*\))+

위와 같이 whitespace, comma, whitespace 후에 새로운 keyword를 받으면 될 것 같지만, 안 된다;
여기까지 포스팅 하고, 추가 분석은 다음에 시간 나면.ㅎㅎ

덤으로, AcroEdit에서 tab는 2칸 띄우는데, SourceInsight에서는 5칸?이어서 보기에 안 좋다.
AcroEdit에서는 tab이 ‘\t’(ASCII 0×09) 대신 ‘ ‘(ASCII 0×20)을 2개 입력하는 것인가?

아무튼 결론은 좋은 editor를 사용하는 것이 중요하다는 거  

댓글 없음:

댓글 쓰기