view paper/chapter4.tex @ 39:a6540714dda9 draft

modify presen
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 28 Feb 2012 20:01:28 +0900
parents 6a667be77762
children
line wrap: on
line source

\chapter{評価}\label{chap:appraising}
今回実装を行った GCC-4.6 ベース と以前のバージョンある GCC-4.4 と GCC-4.5 ベース,
 それと Micro-C の CbC コンパイラでベンチマークを行った.
プログラムは Micro-C のベンチマークにも使用されるものである.
このプログラムは演算と継続を交互に行うものとなっている.
引数 1 は C で書かれたプログラムをただ CbC へと変換したプログラムになる.
引数 2 と 3 は Micro-C 用に手動で最適化を行ったプログラムである.

環境は以下の アーキテクチャと OS になる.
\begin{itemize}
  \item \verb+x86_64+/Linux
  \item \verb+x86_64+/OS X
\end{itemize}
32 bit, 64 bit の動作も確認する.
また, 最適化無し (-O0) と最適化有り (-O2) にかけたコードの比較を行う.
比較の結果を図\ref{fig:conv1_linux}, \ref{fig:conv1_mac} に示す.
ただし GCC-4.6 の最適化無しコードは, コードセグメントに対して末尾最適化を強制したことが
原因で segmentation fault を起こす為除外している.
(また Micro-C の 64bit 版は Linux では動かなかった為 OS X だけとなっている.)

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[width=70mm]{figure/conv1_linux.pdf}
  \end{center}
  \caption{それぞれのコンパイラにより生成されたコードの速度比較(Linux)}
  \label{fig:conv1_linux}
\end{figure}

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[width=70mm]{figure/conv1_mac.pdf}
  \end{center}
  \caption{それぞれのコンパイラにより生成されたコードの速度比較(OS X)}
  \label{fig:conv1_mac}
\end{figure}




\subsection{評価の考察}
まず, Micro-C 版より GCC 版コンパイラの方が結果が良いことが確認できる.
次に GCC-4.5 と GCC-4.6 を比較してみる.
手動で最適化を行なっている引数 2 と 3 の時は余り差は無い.
だが, 引数 1 の時は 32bit, 64bit 共に GCC-4.6 版が 1.5 倍以上早い.


\subsection{アセンブラコードの比較の結果}
では具体的にはどのようなより良い最適化になっているのかを調べてみる.
結果に差の出た引数 1 の時のアセンブラコードを比較した.
まず, プログラムの大まかな流れを図\ref{fig:conv1_arg0}に示す.


\begin{figure}[htpb]
  \begin{center}
    \includegraphics[width=100mm]{figure/conv1_arg0.pdf}
  \end{center}
  \caption{conv1プログラムの挙動}
  \label{fig:conv1_arg0}
\end{figure}
四角は cs を, 矢印は継続を表している.
また, cs の中の処理は演算の部分は省いて継続に関する部分だけにしてある.
プログラムの処理は cs f から継続が始まり cs g\_h1 まで継続を行いループするという流れになる.
注意点としては, cs f\_g1, cs g\_h1 への継続は cs f\_g0, cs f\_g で自作のスタック(実態は構造体)に
関数ポインタを入れて置き継続している部分である.

まず, CbC-GCC-4.5 のアセンブラをみてみると main 関数から``call f''により継続が行われていた.
cs f へと継続後は図\ref{fig:conv1_arg0}に示す通りの動作を行った.

しかし, CbC-GCC-4.6 の方では main 関数からは``call g\_h1''から継続が行われ, loop check 後も
g\_h1 から継続されていた.
この処理を図\ref{fig:conv1_arg0_2}に示す.
\begin{figure}[htpb]
  \begin{center}
    \includegraphics[width=100mm]{figure/conv1_arg0_2.pdf}
  \end{center}
  \caption{conv1プログラムの挙動( CbC-GCC-4.6 )}
  \label{fig:conv1_arg0_2}
\end{figure}

cs f から cs h まで継続の処理はインライン展開によりまとめて計算されて定数として出されていた.
cs g\_h1 と cs f\_g1 の処理がインライン展開されないのは, 関数ポインタとして扱っていた為だと思われる.