view paper/c3.tex @ 101:cf5564c13205

fix
author Masataka Kohagura <kohagura@cr.ie.u-ryukyu.ac.jp>
date Thu, 18 Feb 2016 22:22:58 +0900
parents 4b1ac04e01aa
children
line wrap: on
line source

\chapter{並列処理向け I/O}
ファイル読み込みなどの I/O を含むプログラムは、読み込み時間が Task の処理時間と比較して大きくなってしまう。
計算処理の並列化を図ったとしても I/O がボトルネックになるので、読み込み時間の長さだけプログラム全体の処理速度が遅くなってしまう。
従来の例題のファイル読み込み部分では mmap を利用していたが、読み込みと Task が並列に動くような実装を行ない、プログラム全体の高速化を図った。

本章では mmap による読み込みと並列処理向け I/O について述べる。

\section{mmap}
Cerium の従来の例題ではファイル読み込みを mmap にて実装していた。
mmap は function call 後にすぐにファイルを読みに行くのではなく、仮想メモリ領域にファイルの中身を対応させ、 その後メモリ空間にアクセスされたときに OS が対応したファイルを読み込む。
そのため、mmap によるファイルを読み込みは読み込み後に Task を実行するので、その間は他の CPU が動作せず並列度が落ちる。

また、読み込む方法が OS 依存となってしまうため環境に左右されやすく、プログラムの書き手が読み込みの制御をすることが難しい。

図\ref{fig:mmap}は mmap で読み込んだファイルに対して Task1 、 Task2 が並列で動作し、それぞれの Task がファイルにアクセスしてそれぞれの処理を行うときのモデルである。

Task1 が実行されると仮想メモリ上に対応したファイルが読み込まれ、読み込み後 Task1 の処理が行われる。
それと同時に Task2 も Task1 と同様の処理が行われるが、Task1 が読み込みをしている間 Task2 が読み込みを行わない。

また、Task1 が実行されるときに初めてそれらの領域にファイルが読み込まれるので、Task1 の文字列処理を実行しない限り Task2 がさらに待たされてしまう。

mmap によるファイルの読み込みは Task と並列に実行されるべきであるが、OS の実装に依存してしまう。

\newpage

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.20]{images/cerium/mmap.pdf}
  \end{center}
  \caption{mmap Model}
  \label{fig:mmap}
\end{figure}

\section{Blocked Read}
mmap ではファイル読み込みを細かく設定することができないので、読み込みを制御できるように実装した。さらに、読み込みと Task が並列に動作するようにした。

読み込みを独立した Thread で行ない、ファイルをある程度の大きさ(Block)ごとに読み込む。
そして、読み込まれた部分に対して並列に Task を起動する。
これを Blocked Read と呼び、I/O の読み込みと Task の並列化を図った。

ファイルを読み込む Task (以下、Blocked Read) と、読み込んだファイルに対して計算を行う Task を別々に生成する。
Blocked Read は一度にファイル全体を読み込むのではなく、ある程度の大きさで分割してから読み込みを行う。
分割して読み込んだ範囲に対して Task を実行する。

図\ref{fig:BlockedReadModel} では、Task をn 個単位でまとめた Task Block を生成する。1つのTask はファイルの長さ {\tt L} の部分を処理する。
したがって、1つのTask Block は {\tt L x n} の部分を処理する。

Task Block で計算される領域が Blocked Read で読み込む領域を追い越して実行してしまうと、まだ読み込まれていない領域に対して計算されてしまう。
Blocked Read による読み込みが終わってから TaskBlock が起動されるように、Cerium の API である wait\_for を使って待ち合わせを行う。

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.5]{./images/cerium/blockedread.pdf}
  \end{center}
  \caption{BlockedRead Model}
  \label{fig:BlockedReadModel}
\end{figure}

\section{I/O 専用 thread の追加}
Blocked Read は読み込みを含む処理なので、Blocked Read 1 つあたりの処理時間は大きくなる。
Blocked Read がファイルを読み込む前提で Task がその領域に対して計算を行うので、Blocked Read の処理によってプログラム全体の処理速度が左右されてしまう。

Cerium Task Manager では、それぞれの Task に対してデバイスを設定することができる。
SPE\_ANY 設定をすると、Task Manager が CPU の割り振りを自動的に行う。
しかし、自動的に割り振りを行なってしまうと、Blocked Read Task 間に Task が割り込まれてしまい、読み込みが遅延してしまう可能性がある。
(図\ref{fig:spe_any_blockedread})

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.7]{./images/cerium/speblockedread.pdf}
  \end{center}
  \caption{BlockedRead と Task を同じ thread で動かした場合}
  \label{fig:spe_any_blockedread}
\end{figure}

そこで、Task が Blocked Read Task 間に割り込まれないようにするため、I/O 専用 thread である iO\_0 の設定を追加した。

IO\_0 は SPE\_ANY とは別 thread の scheduler で動作するので、SPE\_ANY で動作している Task に割り込むことはない。
しかし、読み込みの終了を通知し、次の read を行う時に他の Task がスレッドレベルで割り込んでしまう事があるため、
pthread\_getschedparam() で IO\_0 の priority の設定を行う必要がある(図:\ref{fig:iothread_blockedread})。

\begin{figure}[htpb]
  \begin{center}
    \includegraphics[scale=0.7]{./images/cerium/iothread.pdf}
  \end{center}
  \caption{IO Thread による BlockedRead}
  \label{fig:iothread_blockedread}
\end{figure}