Commit dc5168ae authored by Pedro Gonnet's avatar Pedro Gonnet
Browse files

added cascading dependencies to cope with force-split cells. some bloat in the...

added cascading dependencies to cope with force-split cells. some bloat in the cell struct and potential problems with the size of the density array if a pair is force-split more than twice.


Former-commit-id: fc326d4eaec71b38b925cdccac39d3426b186a8a
parent f805a9dc
......@@ -96,7 +96,7 @@ struct cell {
int sortsize;
/* The tasks computing this cell's density. */
struct task *density[27], *force[27];
struct task *density[8*27], *force[8*27];
int nr_density, nr_force;
/* The ghost task to link density to interactions. */
......
......@@ -463,6 +463,7 @@ void engine_repartition ( struct engine *e ) {
void engine_addtasks_send ( struct engine *e , struct cell *ci , struct cell *cj ) {
int k;
struct scheduler *s = &e->sched;
/* Check if any of the density tasks are for the target node. */
for ( k = 0 ; k < ci->nr_density ; k++ )
......@@ -478,13 +479,13 @@ void engine_addtasks_send ( struct engine *e , struct cell *ci , struct cell *cj
struct task *t_rho = scheduler_addtask( &e->sched , task_type_send_rho , task_subtype_none , 2*ci->tag + 1 , 0 , ci , cj , 0 );
/* The send_rho task depends on the cell's ghost task. */
task_addunlock( ci->ghost , t_rho );
scheduler_addunlock( s , ci->ghost , t_rho );
/* The send_rho task should unlock the super-cell's kick2 task. */
task_addunlock( t_rho , ci->super->kick2 );
scheduler_addunlock( s , t_rho , ci->super->kick2 );
/* The send_xv task should unlock the super-cell's ghost task. */
task_addunlock( t_xv , ci->super->ghost );
scheduler_addunlock( s , t_xv , ci->super->ghost );
}
......@@ -509,6 +510,7 @@ void engine_addtasks_send ( struct engine *e , struct cell *ci , struct cell *cj
void engine_addtasks_recv ( struct engine *e , struct cell *c , struct task *t_xv , struct task *t_rho ) {
int k;
struct scheduler *s = &e->sched;
/* Do we need to construct a recv task? */
if ( t_xv != NULL || c->nr_density > 0 ) {
......@@ -520,8 +522,8 @@ void engine_addtasks_recv ( struct engine *e , struct cell *c , struct task *t_x
/* If there has been a higher-up recv task, then these tasks
are implicit and depend on the higher-up task. */
if ( t_xv != NULL ) {
task_addunlock( c->parent->recv_xv , c->recv_xv );
task_addunlock( c->parent->recv_rho , c->recv_rho );
scheduler_addunlock( s , c->parent->recv_xv , c->recv_xv );
scheduler_addunlock( s , c->parent->recv_rho , c->recv_rho );
c->recv_xv->implicit = 1;
c->recv_rho->implicit = 1;
}
......@@ -532,13 +534,13 @@ void engine_addtasks_recv ( struct engine *e , struct cell *c , struct task *t_x
/* Add dependencies if there are density/force tasks. */
for ( k = 0 ; k < c->nr_density ; k++ ) {
task_addunlock( c->recv_xv , c->density[k] );
task_addunlock( c->density[k] , t_rho );
scheduler_addunlock( s , c->recv_xv , c->density[k] );
scheduler_addunlock( s , c->density[k] , t_rho );
}
for ( k = 0 ; k < c->nr_force ; k++ )
task_addunlock( c->recv_rho , c->force[k] );
scheduler_addunlock( s , c->recv_rho , c->force[k] );
if ( c->sorts != NULL )
task_addunlock( c->recv_xv , c->sorts );
scheduler_addunlock( s , c->recv_xv , c->sorts );
}
......@@ -850,7 +852,7 @@ void engine_maketasks ( struct engine *e ) {
for ( j = 0 ; j < 8 ; j++ )
if ( t->ci->progeny[j] != NULL && t->ci->progeny[j]->sorts != NULL ) {
t->ci->progeny[j]->sorts->skip = 0;
task_addunlock( t->ci->progeny[j]->sorts , t );
scheduler_addunlock( sched , t->ci->progeny[j]->sorts , t );
}
if ( t->type == task_type_self ) {
atomic_inc( &t->ci->nr_tasks );
......@@ -900,10 +902,10 @@ void engine_maketasks ( struct engine *e ) {
/* Self-interaction? */
if ( t->type == task_type_self && t->subtype == task_subtype_density ) {
task_addunlock( t , t->ci->super->ghost );
scheduler_addunlock( sched , t , t->ci->super->ghost );
t2 = scheduler_addtask( sched , task_type_self , task_subtype_force , 0 , 0 , t->ci , NULL , 0 );
task_addunlock( t->ci->ghost , t2 );
task_addunlock( t2 , t->ci->super->kick2 );
scheduler_addunlock( sched , t->ci->ghost , t2 );
scheduler_addunlock( sched , t2 , t->ci->super->kick2 );
t->ci->force[ atomic_inc( &t->ci->nr_force ) ] = t2;
}
......@@ -911,15 +913,15 @@ void engine_maketasks ( struct engine *e ) {
else if ( t->type == task_type_pair && t->subtype == task_subtype_density ) {
t2 = scheduler_addtask( sched , task_type_pair , task_subtype_force , 0 , 0 , t->ci , t->cj , 0 );
if ( t->ci->nodeID == e->nodeID ) {
task_addunlock( t->ci->ghost , t2 );
task_addunlock( t , t->ci->super->ghost );
task_addunlock( t2 , t->ci->super->kick2 );
scheduler_addunlock( sched , t->ci->ghost , t2 );
scheduler_addunlock( sched , t , t->ci->super->ghost );
scheduler_addunlock( sched , t2 , t->ci->super->kick2 );
}
if ( t->cj->nodeID == e->nodeID ) {
task_addunlock( t->cj->ghost , t2 );
scheduler_addunlock( sched , t->cj->ghost , t2 );
if ( t->ci->super != t->cj->super ) {
task_addunlock( t , t->cj->super->ghost );
task_addunlock( t2 , t->cj->super->kick2 );
scheduler_addunlock( sched , t , t->cj->super->ghost );
scheduler_addunlock( sched , t2 , t->cj->super->kick2 );
}
}
t->ci->force[ atomic_inc( &t->ci->nr_force ) ] = t2;
......@@ -930,15 +932,15 @@ void engine_maketasks ( struct engine *e ) {
else if ( t->type == task_type_sub && t->subtype == task_subtype_density ) {
t2 = scheduler_addtask( sched , task_type_sub , task_subtype_force , t->flags , 0 , t->ci , t->cj , 0 );
if ( t->ci->nodeID == e->nodeID ) {
task_addunlock( t , t->ci->super->ghost );
task_addunlock( t->ci->ghost , t2 );
task_addunlock( t2 , t->ci->super->kick2 );
scheduler_addunlock( sched , t , t->ci->super->ghost );
scheduler_addunlock( sched , t->ci->ghost , t2 );
scheduler_addunlock( sched , t2 , t->ci->super->kick2 );
}
if ( t->cj != NULL && t->cj->nodeID == e->nodeID ) {
task_addunlock( t->cj->ghost , t2 );
scheduler_addunlock( sched , t->cj->ghost , t2 );
if ( t->ci->super != t->cj->super ) {
task_addunlock( t , t->cj->super->ghost );
task_addunlock( t2 , t->cj->super->kick2 );
scheduler_addunlock( sched , t , t->cj->super->ghost );
scheduler_addunlock( sched , t2 , t->cj->super->kick2 );
}
}
t->ci->force[ atomic_inc( &t->ci->nr_force ) ] = t2;
......@@ -1219,7 +1221,8 @@ void engine_prepare ( struct engine *e ) {
(1 << task_type_send_xv) |
(1 << task_type_recv_xv) |
(1 << task_type_send_rho) |
(1 << task_type_recv_rho) );
(1 << task_type_recv_rho) |
(1 << task_type_link) );
// message( "scheduler_start took %.3f ms." , (double)(getticks() - tic2)/CPU_TPS*1000 );
TIMER_TOC( timer_prepare );
......@@ -1493,7 +1496,7 @@ void engine_step ( struct engine *e ) {
/* First kick. */
if ( e->step == 0 || !( e->policy & engine_policy_fixdt ) ) {
TIMER_TIC
scheduler_start( &e->sched , (1 << task_type_kick1) );
scheduler_start( &e->sched , (1 << task_type_kick1) | (1 << task_type_link) );
engine_launch( e , ( e->nr_threads > 8 ) ? 8 : e->nr_threads );
TIMER_TOC( timer_kick1 );
}
......
......@@ -50,6 +50,53 @@
#include "scheduler.h"
/**
* @brief Add an unlock_task to the given task.
*
* @param s The #scheduler.
* @param ta The unlocking #task.
* @param tb The #task that will be unlocked.
*/
void scheduler_addunlock ( struct scheduler *s , struct task *ta , struct task *tb ) {
/* Main loop. */
while ( 1 ) {
/* Follow the links. */
while ( ta->link != NULL )
ta = ta->link;
/* Get the index of the next free task. */
int ind = atomic_inc( &ta->nr_unlock_tasks );
/* Is there room in this task? */
if ( ind < task_maxunlock ) {
ta->unlock_tasks[ ind ] = tb;
break;
}
/* Otherwise, generate a link task. */
else {
/* Only one thread should have to do this. */
if ( ind == task_maxunlock ) {
ta->link = scheduler_addtask( s , task_type_link , task_subtype_none , ta->flags , 0 , NULL , NULL , 0 );
ta->link->implicit = 1;
ta->unlock_tasks[ ind ] = ta->link;
}
/* Otherwise, reduce the count. */
else
atomic_dec( &ta->nr_unlock_tasks );
}
}
}
/**
* @brief Mapping function to append a ghost task to each cell.
*
......@@ -84,7 +131,7 @@ void scheduler_map_mkghosts ( struct cell *c , void *data ) {
if (c->parent == NULL || c->parent->count >= space_subsize ) {
c->kick1 = scheduler_addtask( s , task_type_kick1 , task_subtype_none , 0 , 0 , c , NULL , 0 );
if ( c->parent != NULL )
task_addunlock( c->kick1 , c->parent->kick1 );
scheduler_addunlock( s , c->kick1 , c->parent->kick1 );
}
/* Append a kick2 task if we are local and the active super cell. */
......@@ -94,7 +141,7 @@ void scheduler_map_mkghosts ( struct cell *c , void *data ) {
/* If we are not the super cell ourselves, make our ghost depend
on our parent cell. */
if ( c->ghost != NULL && c->super != c ) {
task_addunlock( c->parent->ghost , c->ghost );
scheduler_addunlock( s , c->parent->ghost , c->ghost );
c->ghost->implicit = 1;
}
......@@ -128,7 +175,7 @@ void scheduler_map_mkghosts_nokick1 ( struct cell *c , void *data ) {
/* If we are not the super cell ourselves, make our ghost depend
on our parent cell. */
if ( c->super != c ) {
task_addunlock( c->parent->ghost , c->ghost );
scheduler_addunlock( s , c->parent->ghost , c->ghost );
c->ghost->implicit = 1;
}
......@@ -149,7 +196,7 @@ void scheduler_map_mkkick1 ( struct cell *c , void *data ) {
/* Append a kick1 task and make sure the parent depends on it. */
c->kick1 = scheduler_addtask( s , task_type_kick1 , task_subtype_none , 0 , 0 , c , NULL , 0 );
if ( c->parent != NULL )
task_addunlock( c->kick1 , c->parent->kick1 );
scheduler_addunlock( s , c->kick1 , c->parent->kick1 );
/* Set a bogus super cell. */
for ( finger = c ; finger->parent != NULL ; finger = finger->parent );
......@@ -199,11 +246,11 @@ void scheduler_splittasks ( struct scheduler *s ) {
}
/* Empty task? */
if ( t->ci == NULL || ( t->type == task_type_pair && t->cj == NULL ) ) {
/* if ( t->ci == NULL || ( t->type == task_type_pair && t->cj == NULL ) ) {
t->type = task_type_none;
t->skip = 1;
continue;
}
} */
/* Non-local kick task? */
if ( (t->type == task_type_kick1 || t->type == task_type_kick2 ) &&
......@@ -454,7 +501,7 @@ void scheduler_splittasks ( struct scheduler *s ) {
else
ci->sorts->flags |= (1 << sid);
// lock_unlock_blind( &ci->lock );
task_addunlock( ci->sorts , t );
scheduler_addunlock( s , ci->sorts , t );
/* Create the sort for cj. */
// lock_lock( &cj->lock );
......@@ -463,7 +510,7 @@ void scheduler_splittasks ( struct scheduler *s ) {
else
cj->sorts->flags |= (1 << sid);
// lock_unlock_blind( &cj->lock );
task_addunlock( cj->sorts , t );
scheduler_addunlock( s , cj->sorts , t );
}
......@@ -511,6 +558,7 @@ struct task *scheduler_addtask ( struct scheduler *s , int type , int subtype ,
t->tic = 0;
t->toc = 0;
t->nr_unlock_tasks = 0;
t->link = NULL;
/* Init the lock. */
lock_init( &t->lock );
......@@ -613,6 +661,9 @@ void scheduler_reset ( struct scheduler *s , int size ) {
}
/* Reset the task data. */
bzero( s->tasks , sizeof(struct task) * size );
/* Reset the counters. */
s->size = size;
s->nr_tasks = 0;
......
......@@ -86,3 +86,4 @@ void scheduler_map_mkghosts_nokick1 ( struct cell *c , void *data );
void scheduler_map_mkkick1 ( struct cell *c , void *data );
struct task *scheduler_done ( struct scheduler *s , struct task *t );
struct task *scheduler_unlock ( struct scheduler *s , struct task *t );
void scheduler_addunlock ( struct scheduler *s , struct task *ta , struct task *tb );
......@@ -25,7 +25,7 @@
#define space_cellallocchunk 1000
#define space_splitratio 0.875f
#define space_splitsize_default 400
#define space_maxsize_default 3000
#define space_maxsize_default 2000
#define space_subsize_default 5000
#define space_stretch 1.10f
#define space_maxreldx 0.25f
......
......@@ -50,7 +50,7 @@
const char *taskID_names[task_type_count] = {
"none" , "sort" , "self" , "pair" , "sub" , "ghost" ,
"kick1" , "kick2" , "send_xv" , "recv_xv" , "send_rho" ,
"recv_rho" };
"recv_rho" , "link" };
/**
......@@ -222,6 +222,8 @@ void task_rmunlock_blind ( struct task *ta , struct task *tb ) {
void task_addunlock ( struct task *ta , struct task *tb ) {
error( "Use sched_addunlock instead." );
/* Add the lock atomically. */
ta->unlock_tasks[ atomic_inc( &ta->nr_unlock_tasks ) ] = tb;
......
......@@ -20,7 +20,7 @@
/* Some constants. */
#define task_maxwait 3
#define task_maxunlock 64
#define task_maxunlock 31
/* The different task types. */
......@@ -37,6 +37,7 @@ enum task_types {
task_type_recv_xv,
task_type_send_rho,
task_type_recv_rho,
task_type_link,
task_type_count
};
......@@ -72,7 +73,8 @@ struct task {
ticks tic, toc;
int nr_unlock_tasks;
struct task *unlock_tasks[ task_maxunlock ];
struct task *unlock_tasks[ task_maxunlock + 1 ];
struct task *link;
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment