Mercurial > hg > Game > Cerium
changeset 1874:039e6d5cf5b7 draft
improve spe tasklist pipeline
IO thead priority
author | Kohagura |
---|---|
date | Mon, 30 Dec 2013 20:14:33 +0900 |
parents | accb35bd3449 |
children | 2f04c761bf9f |
files | TaskManager/Cell/CellTaskManagerImpl.cc TaskManager/ChangeLog TaskManager/kernel/ppe/CpuThreads.cc TaskManager/kernel/ppe/Sem.cc TaskManager/kernel/ppe/SemMailManager.cc TaskManager/kernel/ppe/SemMailManager.h TaskManager/test/schedparam/Makefile TaskManager/test/schedparam/schedparam.cc |
diffstat | 8 files changed, 244 insertions(+), 117 deletions(-) [+] |
line wrap: on
line diff
--- a/TaskManager/Cell/CellTaskManagerImpl.cc Sat Dec 28 19:30:42 2013 +0900 +++ b/TaskManager/Cell/CellTaskManagerImpl.cc Mon Dec 30 20:14:33 2013 +0900 @@ -154,10 +154,7 @@ void CellTaskManagerImpl::sendTaskList() { for (int id = 0; id < machineNum; id++) { mail_check(id); - if (!speTaskList[id]->empty()) { - continue; // まだ、走ってる - } - if (!taskListInfo[id]->empty()) { + if (speTaskList[id]->empty()) { // SPE に送る TaskList の準備 send_taskList(id); } @@ -171,7 +168,7 @@ } void CellTaskManagerImpl::debug_check_spe_idle( - QueueInfo<HTask> * activeTaskQueue, int spe_running_) { + QueueInfo<HTask> * activeTaskQueue, int spe_running_) { printf("spu_idle! spe_running = %d : activeTaskQueue->length = %d \n", spe_running_, activeTaskQueue->length()); HTaskPtr task = activeTaskQueue->getFirst(); @@ -264,10 +261,6 @@ // MY_SPE_STATUS_READY: SPE が持ってた Task 全て終了 // freeAll する前に循環リストに戻す spe_running--; - if (!speTaskList[id]->empty()) { - speTaskList[id]->getLast()->next = speTaskList[id]; - speTaskList[id]->freeAll(); - } // printf("SPE %d status ready, %d running\n",id, spe_running); } else if (data == (memaddr) MY_SPE_COMMAND_MALLOC) { // MY_SPE_COMMAND_MALLOC SPE からのmain memory request @@ -278,8 +271,17 @@ #ifdef TASK_LIST_MAIL // multi dimensionだったらcount downする TaskListPtr list = (TaskListPtr)data; - if (--list->self->flag.dim_count == 0) + if (--list->self->flag.dim_count == 0) { check_task_list_finish(schedTaskManager, list, waitTaskQueue); + if (speTaskList[id]->getFirst() == list) { + speTaskList[id]->next = list->next; + speTaskList[id]->free_(list); + } + if (taskListInfo[id]->getFirst() == list) { + taskListInfo[id]->next = list->next; + taskListInfo[id]->free_(list); + } + } #else // 終了したタスク(PPEにあるのでアドレス) HTaskPtr task = (HTaskPtr) data;
--- a/TaskManager/ChangeLog Sat Dec 28 19:30:42 2013 +0900 +++ b/TaskManager/ChangeLog Mon Dec 30 20:14:33 2013 +0900 @@ -1,3 +1,17 @@ +2013-12-27 Masataka Kohagura <kohagura@cr.ie.u-ryukyu.ac.jp> + + spe側のTaskListのpipelineの間が空いているので、それを埋める必要がある + speTaskListを処理している間に、次のTaskを送っておく。 + speからTaskList終了mailがきたら、その場でspeTaskListの終了をcheckする。 + speTaskListがemptyならば、speがTaskListInfoを実行中でもsetTaskListしてよい。 + Task終了mailがきたときに、speTaskListとtasklistinfoのどちらかからTaskを取り除く必要がある。 + それはTaskListのアドレスがあるので、自動的に行われる。 + speはすでにTaskListInfo側を実行しているかも知れないが、speTaskListを調べてemptyならばそれを解放する。 + + Semaphore では排他制御されているので、atomic increment の意味はない。 + Synchronied Mail の方では、1対1以外の場合は、atomic incrementする必要がある。(してない) + + 2013-12-27 Masataka Kohagura <kohagura@cr.ie.u-ryukyu.ac.jp> read / write を専用に行うCPU threadを用意する
--- a/TaskManager/kernel/ppe/CpuThreads.cc Sat Dec 28 19:30:42 2013 +0900 +++ b/TaskManager/kernel/ppe/CpuThreads.cc Mon Dec 30 20:14:33 2013 +0900 @@ -66,8 +66,14 @@ manager->set_scheduler(c_scheduler); SchedRegister(ShowTime); SchedRegister(StartProfile); - if (argt->cpuid >= argt->cpu_num) - pthread_setschedparam(static_cast<CpuThreads*>(args)->threads[argt->cpuid], SCHED_OTHER, &(argt->priority)); + if (argt->cpuid >= argt->cpu_num) { + // set IO thread priory maximum + int policy; + struct sched_param param; + pthread_getschedparam(pthread_self(), &policy, ¶m); + param.sched_priority = argt->priority = 1; + pthread_setschedparam(pthread_self(), policy, ¶m); + } argt->wait->sem_v(); //準備完了したスレッドができるたびに+1していく
--- a/TaskManager/kernel/ppe/Sem.cc Sat Dec 28 19:30:42 2013 +0900 +++ b/TaskManager/kernel/ppe/Sem.cc Mon Dec 30 20:14:33 2013 +0900 @@ -29,9 +29,9 @@ pthread_cond_wait(&sem->cond, &sem->mutex); } //atomic - //sem->value--; //資源の確保 + sem->value--; //資源の確保 //count()のvalueを取得する際にアトミック操作が必要 - __sync_fetch_and_sub(&sem->value,1); + //__sync_fetch_and_sub(&sem->value,1); pthread_mutex_unlock(&sem->mutex); } @@ -42,8 +42,8 @@ { pthread_mutex_lock(&sem->mutex); //atomic - //sem->value++; //資源の解放 - __sync_fetch_and_add(&sem->value,1); + sem->value++; //資源の解放 + //__sync_fetch_and_add(&sem->value,1); //資源の解放を知らせる pthread_cond_signal(&sem->cond);
--- a/TaskManager/kernel/ppe/SemMailManager.cc Sat Dec 28 19:30:42 2013 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -#include <stdlib.h> -#include "SemMailManager.h" - -void -SemMailManager::calc_mask(unsigned int qsize) -{ - mask = 1; - while(qsize>mask) { - mask <<= 1; - } - size = mask; - mask--; -} - -SemMailManager::SemMailManager(unsigned int qsize) { - read = write = 0; - calc_mask(qsize); - queue = Newq(memaddr,size); - - queue_remain = new Sem(size-1); //queue内に入る残りの数 - queue_count = new Sem(0); //queue内に現在入っている数 - -} - -SemMailManager::~SemMailManager() -{ - free(queue); - delete queue_remain; - delete queue_count; -} - -int -SemMailManager::count() -{ - return queue_count->count(); -} - -void -SemMailManager::send(memaddr data) -{ - queue_remain->sem_p(); //資源-1 - - queue[write++] = data; - //maskの範囲を超えた場合、0に戻す - write &= mask; - - queue_count->sem_v(); //資源+1 -} - -memaddr -SemMailManager::recv() -{ - queue_count->sem_p(); //資源-1 - - memaddr data; - data = queue[read++]; - read &= mask; - - queue_remain->sem_v(); //資源+1 - - return data; -} - -/* end */
--- a/TaskManager/kernel/ppe/SemMailManager.h Sat Dec 28 19:30:42 2013 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -#ifndef INCLUDED_SEM_MAIL_MANAGER -#define INCLUDED_SEM_MAIL_MANAGER - -#include <pthread.h> -#include "MailManager.h" -#include "types.h" -#include "Sem.h" - -class SemMailManager : public MailManager { -public: - /* constructor */ - SemMailManager(unsigned int qsize = 32) ; - - ~SemMailManager(); - - /* functions */ - void send(memaddr data); - memaddr recv(); - int count(); - -private: - /* variables */ - memaddr *queue; - SemPtr queue_remain; - SemPtr queue_count; - unsigned int size; - unsigned int read; - unsigned int write; - unsigned int mask; - - void calc_mask(unsigned int qsize); - void extend(); -} ; - -typedef SemMailManager *SemMailManagerPtr; - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TaskManager/test/schedparam/Makefile Mon Dec 30 20:14:33 2013 +0900 @@ -0,0 +1,5 @@ +CC = clang++ +CPPFLAGS = -g -O0 +schedparam: schedparam.o + $(CC) -g -O0 -o $@ $< +schedparam.o: schedparam.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TaskManager/test/schedparam/schedparam.cc Mon Dec 30 20:14:33 2013 +0900 @@ -0,0 +1,201 @@ +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#define handle_error_en(en, msg) \ + do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) + +static void +usage(const char *prog_name,const char *msg) +{ + if (msg != NULL) + fputs(msg, stderr); + + fprintf(stderr, "Usage: %s [options]\n", prog_name); + fprintf(stderr, "Options are:\n"); +#define fpe(msg) fprintf(stderr, "\t%s", msg); /* Shorter */ + fpe("-a<policy><prio> Set scheduling policy and priority in\n"); + fpe(" thread attributes object\n"); + fpe(" <policy> can be\n"); + fpe(" f SCHED_FIFO\n"); + fpe(" r SCHED_RR\n"); + fpe(" o SCHED_OTHER\n"); + fpe("-A Use default thread attributes object\n"); + fpe("-i {e|s} Set inherit scheduler attribute to\n"); + fpe(" 'explicit' or 'inherit'\n"); + fpe("-m<policy><prio> Set scheduling policy and priority on\n"); + fpe(" main thread before pthread_create() call\n"); + exit(EXIT_FAILURE); +} + +static int +get_policy(char p, int *policy) +{ + switch (p) { + case 'f': *policy = SCHED_FIFO; return 1; + case 'r': *policy = SCHED_RR; return 1; + case 'o': *policy = SCHED_OTHER; return 1; + default: return 0; + } +} + +static void +display_sched_attr(int policy, struct sched_param *param) +{ + printf(" policy=%s, priority=%d\n", + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + param->sched_priority); +} + +static void +display_thread_sched_attr(const char *msg) +{ + int policy, s; + struct sched_param param; + + s = pthread_getschedparam(pthread_self(), &policy, ¶m); + if (s != 0) + handle_error_en(s, "pthread_getschedparam"); + + printf("%s\n", msg); + display_sched_attr(policy, ¶m); +} + +static void * +thread_start(void *arg) +{ + display_thread_sched_attr("Scheduler attributes of new thread"); + + return NULL; +} + +int +main(int argc, char *argv[]) +{ + int s, opt, inheritsched, use_null_attrib, policy; + pthread_t thread; + pthread_attr_t attr; + pthread_attr_t *attrp; + char *attr_sched_str, *main_sched_str, *inheritsched_str; + struct sched_param param; + + /* Process command-line options */ + + use_null_attrib = 0; + attr_sched_str = NULL; + main_sched_str = NULL; + inheritsched_str = NULL; + + while ((opt = getopt(argc, argv, "a:Ai:m:")) != -1) { + switch (opt) { + case 'a': attr_sched_str = optarg; break; + case 'A': use_null_attrib = 1; break; + case 'i': inheritsched_str = optarg; break; + case 'm': main_sched_str = optarg; break; + default: usage(argv[0], "Unrecognized option\n"); + } + } + + if (use_null_attrib && + (inheritsched_str != NULL || attr_sched_str != NULL)) + usage(argv[0], "Can't specify -A with -i or -a\n"); + + /* Optionally set scheduling attributes of main thread, + * and display the attributes */ + + if (main_sched_str != NULL) { + if (!get_policy(main_sched_str[0], &policy)) + usage(argv[0], "Bad policy for main thread (-s)\n"); + param.sched_priority = strtol(&main_sched_str[1], NULL, 0); + + s = pthread_setschedparam(pthread_self(), policy, ¶m); + if (s != 0) + handle_error_en(s, "pthread_setschedparam"); + } + + display_thread_sched_attr("Scheduler settings of main thread"); + printf("\n"); + + /* Initialize thread attributes object according to options */ + + attrp = NULL; + + if (!use_null_attrib) { + s = pthread_attr_init(&attr); + if (s != 0) + handle_error_en(s, "pthread_attr_init"); + attrp = &attr; + } + + if (inheritsched_str != NULL) { + if (inheritsched_str[0] == 'e') + inheritsched = PTHREAD_EXPLICIT_SCHED; + else if (inheritsched_str[0] == 'i') + inheritsched = PTHREAD_INHERIT_SCHED; + else + usage(argv[0], "Value for -i must be 'e' or 'i'\n"); + + s = pthread_attr_setinheritsched(&attr, inheritsched); + if (s != 0) + handle_error_en(s, "pthread_attr_setinheritsched"); + } + + if (attr_sched_str != NULL) { + if (!get_policy(attr_sched_str[0], &policy)) + usage(argv[0], + "Bad policy for 'attr' (-a)\n"); + param.sched_priority = strtol(&attr_sched_str[1], NULL, 0); + + s = pthread_attr_setschedpolicy(&attr, policy); + if (s != 0) + handle_error_en(s, "pthread_attr_setschedpolicy"); + s = pthread_attr_setschedparam(&attr, ¶m); + if (s != 0) + handle_error_en(s, "pthread_attr_setschedparam"); + } + + /* If we initialized a thread attributes object, display + * the scheduling attributes that were set in the object */ + + if (attrp != NULL) { + s = pthread_attr_getschedparam(&attr, ¶m); + if (s != 0) + handle_error_en(s, "pthread_attr_getschedparam"); + s = pthread_attr_getschedpolicy(&attr, &policy); + if (s != 0) + handle_error_en(s, "pthread_attr_getschedpolicy"); + + printf("Scheduler settings in 'attr'\n"); + display_sched_attr(policy, ¶m); + + s = pthread_attr_getinheritsched(&attr, &inheritsched); + printf(" inheritsched is %s\n", + (inheritsched == PTHREAD_INHERIT_SCHED) ? "INHERIT" : + (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" : + "???"); + printf("\n"); + } + + /* Create a thread that will display its scheduling attributes */ + + s = pthread_create(&thread, attrp, &thread_start, NULL); + if (s != 0) + handle_error_en(s, "pthread_create"); + + /* Destroy unneeded thread attributes object */ + + s = pthread_attr_destroy(&attr); + if (s != 0) + handle_error_en(s, "pthread_attr_destroy"); + + s = pthread_join(thread, NULL); + if (s != 0) + handle_error_en(s, "pthread_join"); + + exit(EXIT_SUCCESS); +}