Mercurial > hg > Members > kono > Cerium
view example/many_task/sort.cc @ 936:14fb1c888931
dead lock on spu/ppu mail
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 31 Jul 2010 05:31:12 +0900 |
parents | e54842e4d97b |
children | 8733ad41297d |
line wrap: on
line source
#include "TaskManager.h" #include "SchedTask.h" #include "sort.h" #include "Func.h" #include <string.h> static void sort_start(SchedTask *); extern void check_data(); static DataPtr data; static int data_length; static int cpuNum; extern int all; /** * 一つの block にある data の数が MAX_BLOCK_SIZE 超えないような * len の分割数を返す * * @param len sort する data の総数 * @param num 使用する SPE の数 * * @return data の分割数 * * TODO: * len が num 以下とか考えてません */ static int get_split_num(int len, int num) { if (len / num < MAX_BLOCK_SIZE) { return num; } else { // 切り上げ return (len + MAX_BLOCK_SIZE - 1) / MAX_BLOCK_SIZE; } } HTaskPtr *fsort; HTaskPtr *bsort; int split_num; /** * btask が全て終了したら、再び sort_start を実行する * @param d 生成された btask の数 */ SchedDefineTask1(RESTART, sort_restart ); static int sort_restart(SchedTask *s, void *d, void *e) { static int ccc = 0; printf("restarted %d %% %d\n",ccc++,split_num); sort_start(s); return 0; } #ifdef USE_SIMPLE_TASK static void sort_start(SchedTask *manager) { int half_num = split_num-1; static int sort_count = split_num; // sort 完了に必要な回数 // 一つのタスクで sort する data 数 int block_num = (data_length + split_num -1)/split_num; int half_block_num = block_num/2; int last_block_num = data_length - (split_num-1)*block_num; int last_half_block_num = half_block_num+(last_block_num/2); if (--sort_count < 0) { return; } for (int i = 0; i < split_num-1; i++) { fsort[i] = manager->create_task(QUICK_SORT, (memaddr)&data[i*block_num], sizeof(Data)*block_num, (memaddr)&data[i*block_num], sizeof(Data)*block_num); if (i>0 && bsort[i-1]) { fsort[i]->wait_for(bsort[i-1]); } if (i<split_num-2 && bsort[i]) { fsort[i]->wait_for(bsort[i]); } fsort[i]->set_cpu(SPE_ANY); } // 最後の block は端数なので last_block_num を使う { int i = split_num-1; fsort[i] = manager->create_task(QUICK_SORT, (memaddr)&data[i*block_num], sizeof(Data)*last_block_num, (memaddr)&data[i*block_num], sizeof(Data)*last_block_num); if (i>0 && bsort[i-1]) { fsort[i]->wait_for(bsort[i-1]); } fsort[i]->set_cpu(SPE_ANY); } if (split_num > 1) { for (int i = 0; i < half_num-1; i++) { bsort[i] = manager->create_task(QUICK_SORT, (memaddr)&data[i*block_num+half_block_num], sizeof(Data)*block_num, (memaddr)&data[i*block_num+half_block_num], sizeof(Data)*block_num); bsort[i]->set_cpu(SPE_ANY); } { int i = half_num-1; bsort[i] = manager->create_task(QUICK_SORT, (memaddr)&data[i*block_num+half_block_num], sizeof(Data)*last_half_block_num, (memaddr)&data[i*block_num+half_block_num], sizeof(Data)*last_half_block_num); bsort[i]->set_cpu(SPE_ANY); } for (int i = 0; i < half_num; i++) { bsort[i]->wait_for(fsort[i]); bsort[i]->wait_for(fsort[i+1]); bsort[i]->spawn(); } } HTaskPtr restart = manager->create_task(RESTART,0,0,0,0); for (int i = 0; i < split_num; i++) { if (!all) restart->wait_for(fsort[i]); fsort[i]->spawn(); } restart->spawn(); } #else static void sort_start(SchedTask *manager) { int half_num = split_num-1; static int sort_count = split_num; // sort 完了に必要な回数 // 一つのタスクで sort する data 数 int block_num = (data_length + split_num -1)/split_num; int half_block_num = block_num/2; int last_block_num = data_length - (split_num-1)*block_num; int last_half_block_num = half_block_num+(last_block_num/2); if (--sort_count < 0) { return; } for (int i = 0; i < split_num-1; i++) { fsort[i] = manager->create_task(QUICK_SORT); fsort[i]->add_inData(&data[i*block_num], sizeof(Data)*block_num); fsort[i]->add_outData(&data[i*block_num], sizeof(Data)*block_num); fsort[i]->set_param(0,(memaddr)block_num); if (i>0 && bsort[i-1]) { fsort[i]->wait_for(bsort[i-1]); } if (i<split_num-2 && bsort[i]) { fsort[i]->wait_for(bsort[i]); } fsort[i]->set_cpu(SPE_ANY); } // 最後の block は端数なので last_block_num を使う { int i = split_num-1; fsort[i] = manager->create_task(QUICK_SORT); fsort[i]->add_inData(&data[i*block_num], sizeof(Data)*last_block_num); fsort[i]->add_outData(&data[i*block_num], sizeof(Data)*last_block_num); fsort[i]->set_param(0,(memaddr)last_block_num); if (i>0 && bsort[i-1]) { fsort[i]->wait_for(bsort[i-1]); } fsort[i]->set_cpu(SPE_ANY); } if (split_num > 1) { HTaskPtr bsort[half_num]; for (int i = 0; i < half_num-1; i++) { bsort[i] = manager->create_task(QUICK_SORT); bsort[i]->add_inData(&data[i*block_num+half_block_num], sizeof(Data)*block_num); bsort[i]->add_outData(&data[i*block_num+half_block_num], sizeof(Data)*block_num); bsort[i]->set_param(0,(memaddr)block_num); bsort[i]->set_cpu(SPE_ANY); } { int i = half_num-1; bsort[i] = manager->create_task(QUICK_SORT); bsort[i]->add_inData(&data[i*block_num+half_block_num], sizeof(Data)*last_half_block_num); bsort[i]->add_outData(&data[i*block_num+half_block_num], sizeof(Data)*last_half_block_num); bsort[i]->set_param(0,(memaddr)last_half_block_num); bsort[i]->set_cpu(SPE_ANY); } for (int i = 0; i < half_num; i++) { bsort[i]->wait_for(fsort[i]); bsort[i]->wait_for(fsort[i+1]); bsort[i]->spawn(); } } HTask *restart = manager->create_task(RESTART,0,0,0,0); for (int i = 0; i < split_num; i++) { if (!all) restart->wait_for(fsort[i]); fsort[i]->spawn(); } restart->spawn(); } #endif void check_data() { int flag = 1; for(int i=0; i< data_length-1;i++) { if (data[i].index>data[i+1].index) { printf("Data are not sorted at %d. %d > %d \n",i, data[i].index,data[i+1].index); flag = 0; break; } } if (flag) printf("Data are sorted\n"); } void sort_init(SchedTask *manager, void *a, void *b) { cpuNum = (int)a; int length = (int)b; data = (DataPtr)manager->allocate(sizeof(Data)*length); data_length = length; split_num = get_split_num(data_length, cpuNum); // data の分割数 int half_num = split_num-1; fsort = (HTaskPtr*)manager->allocate(sizeof(HTaskPtr)*split_num); bsort = (HTaskPtr*)manager->allocate(sizeof(HTaskPtr)*half_num); memset((void*)bsort,0, sizeof(HTaskPtr)*half_num); for (int i = 0; i < length; i++) { data[i].index = manager->get_random()%10000; data[i].ptr = i; } sort_start(manager); } /* end */