Mercurial > hg > Papers > 2014 > masakoha-sigos
view paper/example.tex @ 11:14ce22f649d9
fix
author | Masataka Kohagura <e085726@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 20 Apr 2014 16:25:41 +0900 |
parents | 24384cb335cf |
children | 6f6f482b9f12 |
line wrap: on
line source
\section{Cerium Task Manager を使った例題} \if0 \subsection{ファイルの読み込みに関する例題} テキストファイルをある一定のサイズに分割して読み込むプログラムである。このプログラムでは、pread という関数で実装した。 pread 関数は UNIX 標準に関するヘッダファイル、unistd.h に含まれている関数である。(表\ref{table:pread}) 読み込んだテキストファイルはバッファに格納されるが、その格納先は TaskManager の API でメモリを確保している。 \begin{tiny} \begin{table}[ht] \begin{center} \label{table:pread} \small ssize\_t pread(int fd, void *buf, size\_t nbyte, off\_t offset); \begin{tabular}[t]{c|l} \hline int fd & 読み込むファイルディスクリプタ \\ \hline void *buf & 予め用意したバッファへの書き込み \\ \hline size\_t nbyte & 読み込むサイズ \\ \hline off\_t offset& ファイルの先頭からのオフセット \\ \hline \end{tabular} \caption{pread 関数の概要} \end{center} \end{table} \end{tiny} この例題の Task 生成部分を以下に示す。 \\ \begin{verbatim} HTaskPtr read = manager->create_task(Read_task); read->set_cpu(SPE_ANY); read->set_param(0,(long)task_number); read->set_param(1,(long)division_size); if(read_left_size <= division_size){ read->set_param(2,(long)left_size); }else{ read->set_param(2,(long)division_size); } read->set_param(3,(long)fd); read->set_outData(0,read_text + task_number*division_size, division_size); read->spawn(); left_size -= division_size; task_number++; \end{verbatim} \begin{tiny} \begin{table}[ht] \begin{center} \label{table:pread} \begin{tabular}[t]{c|l} \hline int task\_number & 生成された Task ID \\ \hline division\_size & 1 つの Read Task が読み込む量\\ \hline left\_size & 残りの読み込み量\\ \hline int fd & ファイルディスクリプタ\\ \hline read\_text & 読み込み時に格納する場所の先頭アドレス\\ \hline \end{tabular} \caption{Read Task の生成} \end{center} \end{table} \end{tiny} % % read という Task を宣言し、read に対して CPU Type、生成した Task の番号 task\_number、 % 1つの Task が読み込み量 division\_size、ファイルディスクリプタ fd を設定する。 % 読み込んだデータの格納先を set\_outData にて設定を行い Task を生成する。 % % Task が生成されると、division\_size分の読み込みを行ったということで、残りの読み込み量 read\_left\_size から division\_size を引き、そして task\_numberを増加させる。 % task\_number は ファイルサイズを division\_size で割った数だけ生成され、もし余りがあれば更に1加えた数になる。 % その数が Read Task の数となり、その数だけループ処理を行う。 % 中盤にある if 文は、最後の Read Task かどうかで実際に読み込む量が決定される。 % read Task の記述を以下に示す。 \begin{verbatim} static int read_task(SchedTask *s, void *rbuf, void *wbuf) { long task_number = (long)s->get_param(0); long division_size = (long)s->get_param(1); long read_size = (long)s->get_param(2); long fd = (long)s->get_param(3); char *read_text = (char*)s->get_output(wbuf,0); pread(fd, read_text, (long)read_size, division_size*task_number); return 0; } \end{verbatim} 生成時に設定したデータ群を受け取り、それらのデータを pread の引数に渡す。読み込まれたファイルは read\_text に格納される。 ハードディスクに保存されている 10GB のテキストファイルを分割して読み込み終わるまでの時間を下記に示す。 分割サイズとは、1回の読み込み量である。 \begin{tiny} \begin{table}[ht] \begin{center} \label{table:preaddata} \small \begin{tabular}[t]{c|l} \hline 分割サイズ & 読み込み速度(s)\\ \hline 16KB & 391.7 \\ \hline 16MB & 123.6 \\ \hline \end{tabular} \end{center} \end{table} \end{tiny} 分割サイズを大きくすると、pread の呼ばれる回数が少なくなるので読み込むことが速くなる。 \fi Cerium Task Manager を使った例題として、WordCount を挙げる。このプログラムには、WordCount Task と Print Task の2種類の Task から構成される。 input data とは、mmap や read で読み込んだファイルであり、このファイルを $ n $ KByte の大きさに分割して、WordCount Task にそれぞれ割り当てる。 WordCount Task は、input された data の単語数と行数をカウントし、それらを output に指定された data 領域に書きこむ。 しかし、input data は分割されたデータが送られてくるため、分割された前後のテキストがどうなっているかはわからない。 そのため担当範囲であるデータの先頭と末尾のパラメータを単語数と行数の他に付け加える。後にそのデータを他の WordCount の結果と照らし合わせ、分割されたテキストを正しく整合する。 Print Task は WordCount Task によって書き出された単語数と行数を集計し、結果を出力する Task である。 WordCount Task が全て走り終わったあとに、Print Task が走るように wait をかけている。(図\ref{fig:wordcount}) \begin{figure}[htbp] \begin{center} \includegraphics[scale=0.4]{images/wordcount.pdf} \end{center} \caption{WordCount Model} \label{fig:wordcount} \end{figure}