Commit 88c1e87a authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Separate the time-step communication into different tasks for each type.

parent 65954cff
......@@ -614,26 +614,21 @@ int cell_unpack_tags(const int *tags, struct cell *restrict c) {
*
* @return The number of packed cells.
*/
int cell_pack_end_step(struct cell *restrict c,
struct pcell_step *restrict pcells) {
int cell_pack_end_step_hydro(struct cell *restrict c,
struct pcell_step_hydro *restrict pcells) {
#ifdef WITH_MPI
/* Pack this cell's data. */
pcells[0].hydro.ti_end_min = c->hydro.ti_end_min;
pcells[0].hydro.ti_end_max = c->hydro.ti_end_max;
pcells[0].grav.ti_end_min = c->grav.ti_end_min;
pcells[0].grav.ti_end_max = c->grav.ti_end_max;
pcells[0].stars.ti_end_min = c->stars.ti_end_min;
pcells[0].stars.ti_end_max = c->stars.ti_end_max;
pcells[0].hydro.dx_max_part = c->hydro.dx_max_part;
pcells[0].stars.dx_max_part = c->stars.dx_max_part;
pcells[0].ti_end_min = c->hydro.ti_end_min;
pcells[0].ti_end_max = c->hydro.ti_end_max;
pcells[0].dx_max_part = c->hydro.dx_max_part;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_pack_end_step(c->progeny[k], &pcells[count]);
count += cell_pack_end_step_hydro(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
......@@ -653,26 +648,155 @@ int cell_pack_end_step(struct cell *restrict c,
*
* @return The number of cells created.
*/
int cell_unpack_end_step(struct cell *restrict c,
struct pcell_step *restrict pcells) {
int cell_unpack_end_step_hydro(struct cell *restrict c,
struct pcell_step_hydro *restrict pcells) {
#ifdef WITH_MPI
/* Unpack this cell's data. */
c->hydro.ti_end_min = pcells[0].hydro.ti_end_min;
c->hydro.ti_end_max = pcells[0].hydro.ti_end_max;
c->grav.ti_end_min = pcells[0].grav.ti_end_min;
c->grav.ti_end_max = pcells[0].grav.ti_end_max;
c->stars.ti_end_min = pcells[0].stars.ti_end_min;
c->stars.ti_end_max = pcells[0].stars.ti_end_max;
c->hydro.dx_max_part = pcells[0].hydro.dx_max_part;
c->stars.dx_max_part = pcells[0].stars.dx_max_part;
c->hydro.ti_end_min = pcells[0].ti_end_min;
c->hydro.ti_end_max = pcells[0].ti_end_max;
c->hydro.dx_max_part = pcells[0].dx_max_part;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_unpack_end_step(c->progeny[k], &pcells[count]);
count += cell_unpack_end_step_hydro(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
return count;
#else
error("SWIFT was not compiled with MPI support.");
return 0;
#endif
}
/**
* @brief Pack the time information of the given cell and all it's sub-cells.
*
* @param c The #cell.
* @param pcells (output) The end-of-timestep information we pack into
*
* @return The number of packed cells.
*/
int cell_pack_end_step_grav(struct cell *restrict c,
struct pcell_step_grav *restrict pcells) {
#ifdef WITH_MPI
/* Pack this cell's data. */
pcells[0].ti_end_min = c->grav.ti_end_min;
pcells[0].ti_end_max = c->grav.ti_end_max;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_pack_end_step_grav(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
return count;
#else
error("SWIFT was not compiled with MPI support.");
return 0;
#endif
}
/**
* @brief Unpack the time information of a given cell and its sub-cells.
*
* @param c The #cell
* @param pcells The end-of-timestep information to unpack
*
* @return The number of cells created.
*/
int cell_unpack_end_step_grav(struct cell *restrict c,
struct pcell_step_grav *restrict pcells) {
#ifdef WITH_MPI
/* Unpack this cell's data. */
c->grav.ti_end_min = pcells[0].ti_end_min;
c->grav.ti_end_max = pcells[0].ti_end_max;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_unpack_end_step_grav(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
return count;
#else
error("SWIFT was not compiled with MPI support.");
return 0;
#endif
}
/**
* @brief Pack the time information of the given cell and all it's sub-cells.
*
* @param c The #cell.
* @param pcells (output) The end-of-timestep information we pack into
*
* @return The number of packed cells.
*/
int cell_pack_end_step_stars(struct cell *restrict c,
struct pcell_step_stars *restrict pcells) {
#ifdef WITH_MPI
/* Pack this cell's data. */
pcells[0].ti_end_min = c->stars.ti_end_min;
pcells[0].ti_end_max = c->stars.ti_end_max;
pcells[0].dx_max_part = c->stars.dx_max_part;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_pack_end_step_stars(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
return count;
#else
error("SWIFT was not compiled with MPI support.");
return 0;
#endif
}
/**
* @brief Unpack the time information of a given cell and its sub-cells.
*
* @param c The #cell
* @param pcells The end-of-timestep information to unpack
*
* @return The number of cells created.
*/
int cell_unpack_end_step_stars(struct cell *restrict c,
struct pcell_step_stars *restrict pcells) {
#ifdef WITH_MPI
/* Unpack this cell's data. */
c->stars.ti_end_min = pcells[0].ti_end_min;
c->stars.ti_end_max = pcells[0].ti_end_max;
c->stars.dx_max_part = pcells[0].dx_max_part;
/* Fill in the progeny, depth-first recursion. */
int count = 1;
for (int k = 0; k < 8; k++)
if (c->progeny[k] != NULL) {
count += cell_unpack_end_step_stars(c->progeny[k], &pcells[count]);
}
/* Return the number of packed values. */
......@@ -1846,8 +1970,8 @@ void cell_clear_limiter_flags(struct cell *c, void *data) {
}
/**
* @brief Recurse down in a cell hierarchy until the hydro.super level is reached
* and activate the spart drift at that level.
* @brief Recurse down in a cell hierarchy until the hydro.super level is
* reached and activate the spart drift at that level.
*
* @param c The #cell to recurse into.
* @param s The #scheduler.
......@@ -3146,7 +3270,8 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) {
}
/* If the foreign cell is active, we want its ti_end values. */
if (ci_active || with_limiter) scheduler_activate(s, ci->mpi.recv_ti);
if (ci_active || with_limiter)
scheduler_activate(s, ci->mpi.hydro.recv_ti);
if (with_limiter) scheduler_activate(s, ci->mpi.limiter.recv);
if (with_limiter)
......@@ -3174,7 +3299,7 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) {
/* If the local cell is active, send its ti_end values. */
if (cj_active || with_limiter)
scheduler_activate_send(s, cj->mpi.send_ti, ci_nodeID);
scheduler_activate_send(s, cj->mpi.hydro.send_ti, ci_nodeID);
} else if (cj_nodeID != nodeID) {
......@@ -3191,7 +3316,8 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) {
}
/* If the foreign cell is active, we want its ti_end values. */
if (cj_active || with_limiter) scheduler_activate(s, cj->mpi.recv_ti);
if (cj_active || with_limiter)
scheduler_activate(s, cj->mpi.hydro.recv_ti);
if (with_limiter) scheduler_activate(s, cj->mpi.limiter.recv);
if (with_limiter)
......@@ -3220,7 +3346,7 @@ int cell_unskip_hydro_tasks(struct cell *c, struct scheduler *s) {
/* If the local cell is active, send its ti_end values. */
if (ci_active || with_limiter)
scheduler_activate_send(s, ci->mpi.send_ti, cj_nodeID);
scheduler_activate_send(s, ci->mpi.hydro.send_ti, cj_nodeID);
}
#endif
}
......@@ -3318,7 +3444,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
if (cj_active) scheduler_activate(s, ci->mpi.grav.recv);
/* If the foreign cell is active, we want its ti_end values. */
if (ci_active) scheduler_activate(s, ci->mpi.recv_ti);
if (ci_active) scheduler_activate(s, ci->mpi.grav.recv_ti);
/* Is the foreign cell active and will need stuff from us? */
if (ci_active) {
......@@ -3332,7 +3458,8 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
}
/* If the local cell is active, send its ti_end values. */
if (cj_active) scheduler_activate_send(s, cj->mpi.send_ti, ci_nodeID);
if (cj_active)
scheduler_activate_send(s, cj->mpi.grav.send_ti, ci_nodeID);
} else if (cj_nodeID != nodeID) {
......@@ -3340,7 +3467,7 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
if (ci_active) scheduler_activate(s, cj->mpi.grav.recv);
/* If the foreign cell is active, we want its ti_end values. */
if (cj_active) scheduler_activate(s, cj->mpi.recv_ti);
if (cj_active) scheduler_activate(s, cj->mpi.grav.recv_ti);
/* Is the foreign cell active and will need stuff from us? */
if (cj_active) {
......@@ -3354,7 +3481,8 @@ int cell_unskip_gravity_tasks(struct cell *c, struct scheduler *s) {
}
/* If the local cell is active, send its ti_end values. */
if (ci_active) scheduler_activate_send(s, ci->mpi.send_ti, cj_nodeID);
if (ci_active)
scheduler_activate_send(s, ci->mpi.grav.send_ti, cj_nodeID);
}
#endif
}
......@@ -3527,14 +3655,14 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) {
cell_activate_drift_spart(cj, s);
/* If the local cell is active, send its ti_end values. */
scheduler_activate_send(s, cj->mpi.send_ti, ci_nodeID);
scheduler_activate_send(s, cj->mpi.stars.send_ti, ci_nodeID);
}
if (ci_active) {
scheduler_activate(s, ci->mpi.stars.recv);
/* If the foreign cell is active, we want its ti_end values. */
scheduler_activate(s, ci->mpi.recv_ti);
scheduler_activate(s, ci->mpi.stars.recv_ti);
/* Is the foreign cell active and will need stuff from us? */
scheduler_activate_send(s, cj->mpi.hydro.send_xv, ci_nodeID);
......@@ -3557,14 +3685,14 @@ int cell_unskip_stars_tasks(struct cell *c, struct scheduler *s) {
cell_activate_drift_spart(ci, s);
/* If the local cell is active, send its ti_end values. */
scheduler_activate_send(s, ci->mpi.send_ti, cj_nodeID);
scheduler_activate_send(s, ci->mpi.stars.send_ti, cj_nodeID);
}
if (cj_active) {
scheduler_activate(s, cj->mpi.stars.recv);
/* If the foreign cell is active, we want its ti_end values. */
scheduler_activate(s, cj->mpi.recv_ti);
scheduler_activate(s, cj->mpi.stars.recv_ti);
/* Is the foreign cell active and will need stuff from us? */
scheduler_activate_send(s, ci->mpi.hydro.send_xv, cj_nodeID);
......@@ -3755,7 +3883,9 @@ void cell_set_super_mapper(void *map_data, int num_elements, void *extra_data) {
int cell_has_tasks(struct cell *c) {
#ifdef WITH_MPI
if (c->timestep != NULL || c->mpi.recv_ti != NULL) return 1;
if (c->timestep != NULL || c->mpi.hydro.recv_ti != NULL ||
c->mpi.grav.recv_ti != NULL || c->mpi.stars.recv_ti != NULL)
return 1;
#else
if (c->timestep != NULL) return 1;
#endif
......
......@@ -175,46 +175,37 @@ struct pcell {
/**
* @brief Cell information at the end of a time-step.
*/
struct pcell_step {
struct pcell_step_hydro {
/*! Hydro variables */
struct {
/*! Minimal integer end-of-timestep in this cell (hydro) */
integertime_t ti_end_min;
/*! Minimal integer end-of-timestep in this cell (hydro) */
integertime_t ti_end_min;
/*! Minimal integer end-of-timestep in this cell (hydro) */
integertime_t ti_end_max;
/*! Maximal distance any #part has travelled since last rebuild */
float dx_max_part;
} hydro;
/*! Minimal integer end-of-timestep in this cell (hydro) */
integertime_t ti_end_max;
/*! Grav variables */
struct {
/*! Minimal integer end-of-timestep in this cell (gravity) */
integertime_t ti_end_min;
/*! Maximal distance any #part has travelled since last rebuild */
float dx_max_part;
};
/*! Minimal integer end-of-timestep in this cell (gravity) */
integertime_t ti_end_max;
struct pcell_step_grav {
} grav;
/*! Minimal integer end-of-timestep in this cell (gravity) */
integertime_t ti_end_min;
/*! Stars variables */
struct {
/*! Minimal integer end-of-timestep in this cell (gravity) */
integertime_t ti_end_max;
};
/*! Minimal integer end-of-timestep in this cell (stars) */
integertime_t ti_end_min;
struct pcell_step_stars {
/*! Maximal integer end-of-timestep in this cell (stars) */
integertime_t ti_end_max;
/*! Minimal integer end-of-timestep in this cell (stars) */
integertime_t ti_end_min;
/*! Maximal distance any #part has travelled since last rebuild */
float dx_max_part;
/*! Maximal integer end-of-timestep in this cell (stars) */
integertime_t ti_end_max;
} stars;
/*! Maximal distance any #part has travelled since last rebuild */
float dx_max_part;
};
/**
......@@ -603,6 +594,9 @@ struct cell {
/* Task receiving hydro data (gradient). */
struct task *recv_gradient;
/* Task receiving data (time-step). */
struct task *recv_ti;
/* Linked list for sending hydro data (positions). */
struct link *send_xv;
......@@ -612,6 +606,9 @@ struct cell {
/* Linked list for sending hydro data (gradient). */
struct link *send_gradient;
/* Linked list for sending data (time-step). */
struct link *send_ti;
} hydro;
struct {
......@@ -619,16 +616,30 @@ struct cell {
/* Task receiving gpart data. */
struct task *recv;
/* Task receiving data (time-step). */
struct task *recv_ti;
/* Linked list for sending gpart data. */
struct link *send;
/* Linked list for sending data (time-step). */
struct link *send_ti;
} grav;
struct {
/* Task receiving spart data. */
struct task *recv;
/* Task receiving data (time-step). */
struct task *recv_ti;
/* Linked list for sending spart data. */
struct link *send;
/* Linked list for sending data (time-step). */
struct link *send_ti;
} stars;
struct {
......@@ -639,12 +650,6 @@ struct cell {
struct link *send;
} limiter;
/* Task receiving data (time-step). */
struct task *recv_ti;
/* Linked list for sending data (time-step). */
struct link *send_ti;
/*! Bit mask of the proxies this cell is registered with. */
unsigned long long int sendto;
......@@ -734,8 +739,12 @@ int cell_unpack(struct pcell *pc, struct cell *c, struct space *s,
const int with_gravity);
int cell_pack_tags(const struct cell *c, int *tags);
int cell_unpack_tags(const int *tags, struct cell *c);
int cell_pack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_unpack_end_step(struct cell *c, struct pcell_step *pcell);
int cell_pack_end_step_hydro(struct cell *c, struct pcell_step_hydro *pcell);
int cell_unpack_end_step_hydro(struct cell *c, struct pcell_step_hydro *pcell);
int cell_pack_end_step_grav(struct cell *c, struct pcell_step_grav *pcell);
int cell_unpack_end_step_grav(struct cell *c, struct pcell_step_grav *pcell);
int cell_pack_end_step_stars(struct cell *c, struct pcell_step_stars *pcell);
int cell_unpack_end_step_stars(struct cell *c, struct pcell_step_stars *pcell);
int cell_pack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_unpack_multipoles(struct cell *c, struct gravity_tensors *m);
int cell_getsize(struct cell *c);
......
......@@ -2382,60 +2382,45 @@ void engine_barrier(struct engine *e) {
* @param c The #cell to recurse into.
* @param e The #engine.
*/
void engine_collect_end_of_step_recurse(struct cell *c,
const struct engine *e) {
void engine_collect_end_of_step_recurse_hydro(struct cell *c,
const struct engine *e) {
/* Skip super-cells (Their values are already set) */
#ifdef WITH_MPI
if (c->timestep != NULL || c->mpi.recv_ti != NULL) return;
if (c->timestep != NULL || c->mpi.hydro.recv_ti != NULL) return;
#else
if (c->timestep != NULL) return;
#endif /* WITH_MPI */
#ifdef SWIFT_DEBUG_CHECKS
/* if (!c->split) error("Reached a leaf without finding a time-step task!
* c->depth=%d c->maxdepth=%d c->count=%d c->node=%d", */
/* c->depth, c->maxdepth, c->hydro.count, c->nodeID); */
#endif
/* Counters for the different quantities. */
size_t updated = 0, g_updated = 0, s_updated = 0;
size_t inhibited = 0, g_inhibited = 0, s_inhibited = 0;
size_t updated = 0, inhibited = 0;
integertime_t ti_hydro_end_min = max_nr_timesteps, ti_hydro_end_max = 0,
ti_hydro_beg_max = 0;
integertime_t ti_gravity_end_min = max_nr_timesteps, ti_gravity_end_max = 0,
ti_gravity_beg_max = 0;
integertime_t ti_stars_end_min = max_nr_timesteps, ti_stars_end_max = 0,
ti_stars_beg_max = 0;
/* Collect the values from the progeny. */
for (int k = 0; k < 8; k++) {
struct cell *cp = c->progeny[k];
if (cp != NULL &&
(cp->hydro.count > 0 || cp->grav.count > 0 || cp->stars.count > 0)) {
if (cp != NULL && cp->hydro.count > 0) {
/* Recurse */
engine_collect_end_of_step_recurse(cp, e);
engine_collect_end_of_step_recurse_hydro(cp, e);
/* And update */
ti_hydro_end_min = min(ti_hydro_end_min, cp->hydro.ti_end_min);
ti_hydro_end_max = max(ti_hydro_end_max, cp->hydro.ti_end_max);
ti_hydro_beg_max = max(ti_hydro_beg_max, cp->hydro.ti_beg_max);
ti_gravity_end_min = min(ti_gravity_end_min, cp->grav.ti_end_min);
ti_gravity_end_max = max(ti_gravity_end_max, cp->grav.ti_end_max);
ti_gravity_beg_max = max(ti_gravity_beg_max, cp->grav.ti_beg_max);
ti_stars_end_min = min(ti_stars_end_min, cp->stars.ti_end_min);
ti_stars_end_max = max(ti_stars_end_max, cp->stars.ti_end_max);
ti_stars_beg_max = max(ti_stars_beg_max, cp->stars.ti_beg_max);
updated += cp->hydro.updated;
g_updated += cp->grav.updated;
s_updated += cp->stars.updated;
inhibited += cp->hydro.inhibited;
g_inhibited += cp->grav.inhibited;
s_inhibited += cp->stars.inhibited;
/* Collected, so clear for next time. */
cp->hydro.updated = 0;
cp->grav.updated = 0;
cp->stars.updated = 0;
}
}
......@@ -2443,18 +2428,125 @@ void engine_collect_end_of_step_recurse(struct cell *c,
c->hydro.ti_end_min = ti_hydro_end_min;
c->hydro.ti_end_max = ti_hydro_end_max;
c->hydro.ti_beg_max = ti_hydro_beg_max;
c->grav.ti_end_min = ti_gravity_end_min;
c->grav.ti_end_max = ti_gravity_end_max;
c->grav.ti_beg_max = ti_gravity_beg_max;
c->hydro.updated = updated;
c->hydro.inhibited = inhibited;
}
/**
* @brief Recursive function gathering end-of-step data.
*
* We recurse until we encounter a timestep or time-step MPI recv task
* as the values will have been set at that level. We then bring these
* values upwards.
*
* @param c The #cell to recurse into.
* @param e The #engine.
*/
void engine_collect_end_of_step_recurse_grav(struct cell *c,
const struct engine *e) {
/* Skip super-cells (Their values are already set) */
#ifdef WITH_MPI
if (c->timestep != NULL || c->mpi.grav.recv_ti != NULL) return;
#else
if (c->timestep != NULL) return;
#endif /* WITH_MPI */
#ifdef SWIFT_DEBUG_CHECKS
// if (!c->split) error("Reached a leaf without finding a time-step
// task!");
#endif
/* Counters for the different quantities. */
size_t updated = 0, inhibited = 0;
integertime_t ti_grav_end_min = max_nr_timesteps, ti_grav_end_max = 0,
ti_grav_beg_max = 0;
/* Collect the values from the progeny. */
for (int k = 0; k < 8; k++) {
struct cell *cp = c->progeny[k];
if (cp != NULL && cp->grav.count > 0) {
/* Recurse */
engine_collect_end_of_step_recurse_grav(cp, e);
/* And update */
ti_grav_end_min = min(ti_grav_end_min, cp->grav.ti_end_min);
ti_grav_end_max = max(ti_grav_end_max, cp->grav.ti_end_max);
ti_grav_beg_max = max(ti_grav_beg_max, cp->grav.ti_beg_max);
updated += cp->grav.updated;
inhibited += cp->grav.inhibited;
/* Collected, so clear for next time. */
cp->grav.updated = 0;
}
}
/* Store the collected values in the cell. */
c->grav.ti_end_min = ti_grav_end_min;
c->grav.ti_end_max = ti_grav_end_max;
c->grav.ti_beg_max = ti_grav_beg_max;
c->grav.updated = updated;
c->grav.inhibited = inhibited;
}
/**
* @brief Recursive function gathering end-of-step data.
*
* We recurse until we encounter a timestep or time-step MPI recv task
* as the values will have been set at that level. We then bring these
* values upwards.
*
* @param c The #cell to recurse into.
* @param e The #engine.
*/
void engine_collect_end_of_step_recurse_stars(struct cell *c,
const struct engine *e) {
/* Skip super-cells (Their values are already set) */