changeset 372:d6ce4273e7d1

Add dimension task spawn
author Tatsuki IHA <innparusu@cr.ie.u-ryukyu.ac.jp>
date Tue, 11 Jul 2017 17:47:11 +0900
parents c3a7a086e82a
children 03fdea4ef680
files src/parallel_execution/CPUWorker.cbc src/parallel_execution/TaskManagerImpl.cbc src/parallel_execution/context.h src/parallel_execution/generate_stub.pl
diffstat 4 files changed, 84 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/CPUWorker.cbc	Fri Jul 07 14:58:26 2017 +0900
+++ b/src/parallel_execution/CPUWorker.cbc	Tue Jul 11 17:47:11 2017 +0900
@@ -88,8 +88,9 @@
 }
 
 __code odgCommit3(struct TaskManager* taskManager, struct Context* task) {
-    if(__sync_fetch_and_sub(&task->idgCount, 1)) {
-        if(task->idgCount == 0) {
+    int idgCount = task->idgCount;
+    if(__sync_bool_compare_and_swap(&task->idgCount, idgCount, idgCount-1)) { // atomic decrement idg counter
+        if(idgCount-1 == 0) {
             taskManager->taskManager = (union Data*)task->taskManager;
             taskManager->context = task;
             taskManager->next = C_odgCommit1;
--- a/src/parallel_execution/TaskManagerImpl.cbc	Fri Jul 07 14:58:26 2017 +0900
+++ b/src/parallel_execution/TaskManagerImpl.cbc	Tue Jul 11 17:47:11 2017 +0900
@@ -27,6 +27,23 @@
     return taskManager;
 }
 
+struct Context* cloneTask(struct Context* task) {
+    struct Context* task1 = NEW(struct Context);
+    task1->next = task->next;
+
+    for(int i = task->idg; i < task->maxOdg; i++) {
+        task1->data[i] = task->data[i];
+    }
+
+    task1->dim      = 0;
+    task1->idgCount = 0;
+    task1->idg      = task->idg;
+    task1->maxIdg   = task->maxIdg;
+    task1->odg      = task->odg;
+    task1->maxOdg   = task->maxOdg;
+    return task1;
+}
+
 void createWorkers(struct Context* context, TaskManager* taskManager, TaskManagerImpl* taskManagerImpl) {
     int i = 0;
     taskManagerImpl->workers = (Worker**)ALLOC_ARRAY(context, Worker, taskManager->maxCPU);
@@ -53,14 +70,14 @@
     }
 }
 
-__code spawnTasksTaskManager(struct TaskManager* taskManager, struct TaskManagerImpl* taskManagerImpl, struct Context** contexts) {
+__code spawnTasksTaskManager(struct TaskManager* taskManager, struct TaskManagerImpl* taskManagerImpl, struct Context** tasks) {
     int i = taskManagerImpl->loopCounter->i;
-    struct Context* task = contexts[i];
-    if(i < GET_SIZE(contexts)) {
+    if(i < GET_SIZE(tasks)) {
+        struct Context* task = tasks[i];
         taskManagerImpl->loopCounter->i++;
         taskManager->context = task;
         taskManager->next = C_spawnTasksTaskManager;
-        goto meta(context, C_setWorker);
+        goto meta(context, C_setWaitTask);
     }
     taskManagerImpl->loopCounter->i = 0;
     goto meta(context, C_spawnTasksTaskManager1);
@@ -74,10 +91,10 @@
                                Gearef(context, TaskManager)->contexts);
 }
 
-__code spawnTasksTaskManager1(struct TaskManager* taskManager, struct TaskManagerImpl* taskManagerImpl, struct Context** contexts, __code next(...)) {
+__code spawnTasksTaskManager1(struct TaskManager* taskManager, struct TaskManagerImpl* taskManagerImpl, struct Context** tasks, __code next(...)) {
     int i = taskManagerImpl->loopCounter->i;
-    struct Context* task = contexts[i];
-    if(i < GET_SIZE(contexts)) {
+    if(i < GET_SIZE(tasks)) {
+        struct Context* task = tasks[i];
         taskManagerImpl->loopCounter->i++;
         taskManager->context = task;
         taskManager->next = C_spawnTasksTaskManager1;
@@ -96,26 +113,13 @@
                                Gearef(context, TaskManager)->next1);
 }
 
-__code setWorker(struct TaskManagerImpl* taskManager, struct Context* task) {
-    task->workerId = taskManager->sendWorkerIndex;
-    if(++taskManager->sendWorkerIndex >= taskManager->numWorker) {
-        taskManager->sendWorkerIndex = 0;
-    }
-    goto meta(context, C_setWaitTask);
-}
-
-__code setWorker_stub(struct Context* context) {
-    TaskManagerImpl* taskManager = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
-    goto setWorker(context, taskManager, Gearef(context, TaskManager)->context);
-}
-
-__code setWaitTask(struct Queue* queue, struct Context* task, struct LoopCounter* loopCounter, __code next(...)) {
+__code setWaitTask(struct Queue* queue, struct LoopCounter* loopCounter, struct Context* task, __code next(...)) {
     int i = loopCounter->i;
-    if(task->idg + i < task->maxIdg) {
-        loopCounter->i++;
+    if(task->idg+i < task->maxIdg) {
         queue->queue = (Data *)GET_WAIT_LIST(task->data[task->idg + i]);
-        queue->next = C_setWaitTask;
-        queue->data = (Data *)task;
+        queue->next  = C_setWaitTask;
+        queue->data  = (Data *)task;
+        loopCounter->i++;
         goto meta(context, queue->queue->Queue.put);
     }
     loopCounter->i = 0;
@@ -124,11 +128,52 @@
 
 __code setWaitTask_stub(struct Context* context) {
     struct Context* task = Gearef(context, TaskManager)->context;
-    goto setWaitTask(context, Gearef(context, Queue), task, Gearef(task, LoopCounter), Gearef(context, TaskManager)->next);
+    goto setWaitTask(context,
+                     Gearef(context, Queue),
+                     Gearef(task, LoopCounter),
+                     task,
+                     Gearef(context, TaskManager)->next);
+}
+
+__code dimensionTaskSpawn(struct TaskManagerImpl* taskManager, struct Queue* queue, struct LoopCounter* loopCounter, struct Context* task, __code next(...)) {
+    int i = loopCounter->i;
+    int dimCount = task->x * task->y * task->z;
+    // TODO: implement 3-dimension
+    if(i < dimCount) {
+        loopCounter->i++;
+        struct Context* dimTask = cloneTask(task);
+        task->workerId = taskManager->sendWorkerIndex;
+        struct Queue* tasks = taskManager->workers[task->workerId]->tasks;
+        queue->queue = (union Data*)tasks;
+        queue->data = (union Data*)dimTask;
+        queue->next = C_dimensionTaskSpawn;
+        pthread_mutex_unlock(&taskManager->mutex);
+        goto meta(context, tasks->put);
+    }
+    goto next(...);
+}
+
+__code dimensionTaskSpawn_stub(struct Context* context) {
+    TaskManagerImpl* taskManager = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    struct Context* task = Gearef(context, TaskManager)->context;
+    goto dimensionTaskSpawn(context,
+                          taskManager,
+                          Gearef(context, Queue),
+                          Gearef(task, LoopCounter),
+                          task,
+                          Gearef(context, TaskManager)->next);
 }
 
 __code spawnTaskManager(struct TaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
     if (task->idgCount == 0) {
+        if(context->dim) {
+            goto meta(context, C_dimensionTaskSpawn);
+        }
+        // set workerId
+        task->workerId = taskManager->sendWorkerIndex;
+        if(++taskManager->sendWorkerIndex >= taskManager->numWorker) {
+            taskManager->sendWorkerIndex = 0;
+        }
         goto meta(context, C_taskSend);
     } else {
         pthread_mutex_unlock(&taskManager->mutex);
--- a/src/parallel_execution/context.h	Fri Jul 07 14:58:26 2017 +0900
+++ b/src/parallel_execution/context.h	Tue Jul 11 17:47:11 2017 +0900
@@ -94,6 +94,13 @@
     CUfunction function;
 #endif 
     union Data **data;
+
+    /* multi dimension parameter */
+    struct Context* contexts;
+    int dim;
+    int x;
+    int y;
+    int z;
 };
 
 union Data {
--- a/src/parallel_execution/generate_stub.pl	Fri Jul 07 14:58:26 2017 +0900
+++ b/src/parallel_execution/generate_stub.pl	Tue Jul 11 17:47:11 2017 +0900
@@ -38,59 +38,21 @@
 my %outputArgs;      # continuation's output variables
 my %dataGear;
 my %dataGearName;
-my %generic;
-my %dataGearVarType;
 my $implementation;
 my $interface;
 
-# interface definision
-#
-# typedef struct Stack<Type, Impl>{
-#         Type* stack;
-#         Type* data;
-#         Type* data1;
-#         __code whenEmpty(...);
-#         __code clear(Impl* stack,__code next(...));
-#         __code push(Impl* stack,Type* data, __code next(...));
-#         __code pop(Impl* stack, __code next(Type*, ...));
-#         __code pop2(Impl* stack, Type** data, Type** data1, __code next(Type**, Type**, ...));
-#         __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...));
-#         __code get(Impl* stack, Type** data, __code next(...));
-#         __code get2(Impl* stack,..., __code next(...));
-#         __code next(...);
-# } Stack;
-#
-# calling example
-#
-# goto nodeStack->push((union Data*)node, stackTest3);
-#
-# generated meta level code
-#
-# Gearef(context, Stack)->stack = nodeStack->stack;
-# Gearef(context, Stack)->data = (union Data*)node;
-# Gearef(context, Stack)->next = C_stackTest3;
-# goto meta(context, nodeStack->push);
-
 sub getDataGear {
     my ($filename) = @_;
     my ($codeGearName, $name, $inTypedef);
     open my $fd,"<",$filename or die("can't open $filename $!");
     while (<$fd>) {
         if (! $inTypedef) {
-            if (/^typedef struct (\w+)\s*<(.*)>/) {
+            if (/^typedef struct (\w+)/) {
                 $inTypedef = 1;
                 $name = $1;
                 $dataGear{$name} = $_;
                 $var{$name} = {};
                 $code{$name} = {};
-                $generic{$name} = \split(/,/,$2);
-            } elsif (/^typedef struct (\w+)/) {
-                $inTypedef = 1;
-                $name = $1;
-                $dataGear{$name} = $_;
-                $var{$name} = {};
-                $code{$name} = {};
-                $generic{$name} = [];
             } elsif (/^(\w+)(\*)+ create(\w+)\(/) {
                 if (defined $interface) {
                    die "duplicate interface $interface\n"; 
@@ -112,29 +74,8 @@
                 $ttype = $2;
             }
             $var{$name}->{$tname} = $ttype;
-        } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) {
-            my $args = $2;
-            my $method = $1;
-            $code{$name}->{$method} = [];
-            while($args) {
-                if ($args =~ s/(^\s*,\s*)//) {
-                }
-                # continuation case
-                if ($args =~ s/^(\s)*\_\_code\s+(\w+)\(([^)]*)\)//) {
-                    my $next = $2;
-                    my @args = split(/,/,$3);
-                    push(@{$code{$name}->{$method}},$next); 
-                } elsif ($args =~ s/^(struct|union) (\w+)(\*)+\s(\w+)//) {
-                    my $structType = $1;
-                    my $typeName = $2;
-                    my $varName = $4;
-                    my $typeField = lcfirst($typeName);
-                    push(@{$code{$name}->{$method}},$varName); 
-                } elsif ($args =~ s/(.*,)//) {
-                } else {
-                    last;
-                }
-            }
+	} elsif (/\_\_code (\w+)\(/) {
+            $code{$name}->{$1} = 1;
         }
         if (/^}/) {
             $inTypedef = 0;
@@ -158,7 +99,6 @@
         return 0 if ( $n eq $varname1);
     }
     push @{$dataGearVar{$codeGearName}}, $varname1;
-    push @{$dataGearVarType{$codeGearName}}, $typeName;
     if ($typeName eq $implementation) {
         # get implementation
         $dataGearName{$codeGearName} .= "\t$typeName* $varName = ($typeName*)GearImpl(context, $interface, $varName);\n";
@@ -313,31 +253,6 @@
                     print $fd $outputVar{$codeGearName};
                 }
                 next;
-            } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) {
-                # handling goto statement  
-                # convert it to the meta call form with two arugments, that is context and enum Code
-                my $prev = $1;
-                my $next = $2;
-                my $method = $3;
-                my @args = split(/,/,$4);
-                my @types = @{$dataGearVarType{$codeGearName}};
-                my $ntype;
-                for my $v (@{$dataGearVar{$codeGearName}}) {
-                    my $t = shift @types;
-                    if ($v eq $next) {
-                        $ntype = $t;
-                    }
-                }
-                print $fd "\tGearef(context, $ntype)->$next = $next->$next;\n";
-                # Put interface argument 
-                my $prot = $code{$ntype}->{$method};
-                for my $arg (@args) {
-                    my $p = shift @$prot;
-                    next if ($p eq $arg);
-                    print $fd "\tGearef(context, $ntype)->$p = $arg;\n";
-                }
-                print $fd "${prev}goto meta(context, $next->$next->$ntype.$method);\n";
-                next;
             } elsif (/^(.*)goto (\w+)\((.*)\);/) {
                 # handling goto statement  
                 # convert it to the meta call form with two arugments, that is context and enum Code