Mercurial > hg > Members > e085722 > Cerium
diff example/grep/main.cc @ 0:04e28d8d3c6f
first commit
author | Daiki KINJYO <e085722@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 08 Nov 2010 01:23:25 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example/grep/main.cc Mon Nov 08 01:23:25 2010 +0900 @@ -0,0 +1,221 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include "TaskManager.h" +#include "SchedTask.h" +#include "Func.h" +#include "WordGrep.h" +extern void task_init(); + +int all = 0; +int use_task_array = 0; +int use_compat = 0; +int array_task_num = 8; +int spe_num = 1; +int num = 0; + +//static int blocks = 48; +//static int division = 1024*10; +//static int division_int = 4096; + + +static int blocks = 2; +static int division = 5; +static int division_int = 5; + +int first_over_lap; +int over_lap; + +#define READBUF 1024*16 + +const char *usr_help_str = "Usage: ./word_count [-file filename]\n"; + +SchedDefineTask1(RUN_TASK_BLOCKS,run16); + +typedef struct { + caddr_t file_mmap; + off_t size; +}st_mmap_t; + +/*与えられたsizeをfix_byte_sizeの倍数にする*/ +static int fix_byte(int size,int fix_byte_size){ + size = (size/fix_byte_size)*fix_byte_size + + ((size%fix_byte_size)!= 0)*fix_byte_size; + return size; +} + +static st_mmap_t my_mmap(char *filename){ + /*マッピングしてその場所を返す*/ + int fd = -1; + int map = MAP_PRIVATE; + st_mmap_t st_mmap; + struct stat sb; + /*ファイルオープン*/ + if ((fd=open(filename,O_RDONLY,0666))==0){ + fprintf(stderr,"can't open %s\n",filename); + } /*ファイルが使われていないか*/ + if (fstat(fd,&sb)) { + fprintf(stderr,"can't fstat %s\n",filename); + } /*sizeをページングサイズの倍数にあわせる*/ + st_mmap.size = fix_byte(sb.st_size,division_int); + /*マッピングしてその場所を返す*/ + st_mmap.file_mmap = + (char*)mmap(NULL,st_mmap.size,PROT_READ,map,fd,(off_t)0); + if (st_mmap.file_mmap == (caddr_t)-1) { + perror(NULL); exit(0); + } + return st_mmap; +} + + + +/*タスク生成*/ +static void run_tasks(SchedTask *manager, WordGrep *w, int task_count, HTaskPtr t_next, int size) { + over_lap = first_over_lap; + /*タスク数が1つのspeで処理する数より少なければその数を処理する*/ + if (task_count < array_task_num) { + array_task_num = task_count; + } + //全タスクのループ + for (int i = 0; i < task_count;i+= array_task_num) { + HTask *h_exec = 0; + //blockごとのループ + for (int j = 0; j < array_task_num;j++) { + int i = w->task_spawned++; + + //タスクが最後の場合その分だけ処理 + if (w->size <= size + over_lap) { + size = w->size; + over_lap = 0; + } + if (size==0) break; + /*オーバーラップした文字列を生成してタスク生成*/ + h_exec = manager->create_task(TASK_EXEC); + h_exec->set_inData( + 0,w->file_mmap + i*w->division_size, + size+over_lap); + h_exec->set_outData( + 0,w->o_data + i*w->out_size, + w->division_out_size); + t_next->wait_for(h_exec); + /*タスク実行*/ + h_exec->set_cpu(SPE_ANY); + h_exec->spawn(); + /*終了した分サイズをタスク数を引く*/ + w->size -= size; + w->task_num--; + } + } +} + +/** * このTaskは、PPE上で実行されるので、並列に実行されることはない + * 二つ実行されていて、Task が足りなくなることがないようにしている。 + */ + +static int run16(SchedTask *manager, void *in, void *out){ + WordGrep *w = *(WordGrep **)in; + /*タスク数が1ブロックで処理できる数よりも少ない場合*/ + /*if (!(w->size > w->division_size))でも同じ*/ + if(w->task_num <= w->task_blocks) { + if (w->size == w->division_size) { + run_tasks(manager,w,w->task_num, + w->t_print, w->division_size); + } else { + run_tasks(manager,w,1, w->t_print, w->size); + } + } else { + HTaskPtr t_next = manager->create_task(RUN_TASK_BLOCKS, + (memaddr)&w->self,sizeof(memaddr),0,0); + w->t_print->wait_for(t_next); + run_tasks(manager,w, w->task_blocks, t_next, w->division_size); + t_next->spawn(); + } + return 0; +} + + + +static void run_start(TaskManager *manager, char *filename){ + HTaskPtr t_print; + st_mmap_t st_mmap; + st_mmap = my_mmap(filename); + WordGrep *w = (WordGrep*)manager->allocate(sizeof(WordGrep)); + w->self = w; + w->task_spawned = 0; + + /*sizeはdivision_sizeの倍数にしている。*/ + w->size = w->file_size = st_mmap.size; + w->file_mmap = st_mmap.file_mmap; + /* 1task分のデータサイズ(byte) */ + if (w->size >= division){ + w->division_size = division; + } else { + w->division_size = w->size; + } + /* "word num" and "line num" */ + //w->status_num = 2; + /*taskの数 */ + w->task_num = w->size / w->division_size; + w->task_num = w->task_num + (w->division_size*w->task_num < w->size); + + int out_task_num = w->task_num; + w->out_task_num = out_task_num; + w->task_blocks = blocks; + + /* out用のdivision_size.statusが1つなので、最大16byteになるように*/ + w->division_out_size = sizeof(unsigned long long)*4; + int out_size = w->division_out_size*out_task_num; + w->o_data = (int*)manager->allocate(out_size); + w->out_size = 4; + + + /*各SPEの結果を合計して出力するタスク*/ + t_print = manager->create_task( + TASK_PRINT,(memaddr)&w->self,sizeof(memaddr),0,0); + w->t_print = t_print; + for(int i = 0;i<1;i++) { + /* Task を task_blocks ずつ起動する Task */ + /*serialize されていると仮定する... */ + HTaskPtr t_exec= manager->create_task( + RUN_TASK_BLOCKS,(memaddr)&w->self,sizeof(memaddr),0,0); + t_print->wait_for(t_exec); + t_exec->spawn(); + } + t_print->spawn(); +} + +static char* init(int argc, char **argv){ + char *filename = 0; + use_task_array = 0; + for (int i = 1; argv[i]; ++i) { + if (strcmp(argv[i], "-file") == 0) { + filename = argv[i+1]; + } else if (strcmp(argv[i], "-cpu") == 0) { + spe_num = atoi(argv[i+1]); + } + } + first_over_lap = 2; + over_lap = first_over_lap; + if (filename==0) { + puts(usr_help_str); + exit(1); + } + return filename; +} + + +int TMmain(TaskManager *manager, int argc, char *argv[]){ + char *filename = 0; //引数の入力 + filename = init(argc, argv); + if (filename < 0) { + return -1; + } + task_init(); + run_start(manager, filename); + return 0; +}