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 */