Commit e2650d1d authored by Peter W. Draper's avatar Peter W. Draper
Browse files

Merge branch 'free-sorts' into 'master'

Free sort indices and task arrays before repartitioning

Freeing the sort indices and tasks arrays before repartitioning makes that memory available so 
that we have more room for accepting particles from other nodes.

Part of #98.

Also adds a useful debug function that reports the current memory
usage of the process tree (i.e. call from main thread to get all usage).
Same numbers you get out of the top program.

Free the task arrays and cells are refactored into simple functions to cut down
on cut and paste.

See merge request !392
parents 31883c2e 888f5c2a
......@@ -26,6 +26,7 @@
/* Some standard headers. */
#include <float.h>
#include <stdio.h>
#include <unistd.h>
/* This object's header. */
#include "debug.h"
......@@ -450,3 +451,69 @@ void dumpCellRanks(const char *prefix, struct cell *cells_top, int nr_cells) {
}
#endif /* HAVE_MPI */
/**
* @brief parse the process /proc/self/statm file to get the process
* memory use (in KB). Top field in ().
*
* @param size total virtual memory (VIRT)
* @param resident resident non-swapped memory (RES)
* @param share shared (mmap'd) memory (SHR)
* @param trs text (exe) resident set (CODE)
* @param lrs library resident set
* @param drs data+stack resident set (DATA)
* @param dt dirty pages (nDRT)
*/
void getProcMemUse(long *size, long *resident, long *share, long *trs,
long *lrs, long *drs, long *dt) {
/* Open the file. */
FILE *file = fopen("/proc/self/statm", "r");
if (file != NULL) {
int nscan = fscanf(file, "%ld %ld %ld %ld %ld %ld %ld", size, resident,
share, trs, lrs, drs, dt);
if (nscan == 7) {
/* Convert pages into bytes. Usually 4096, but could be 512 on some
* systems so take care in conversion to KB. */
long sz = sysconf(_SC_PAGESIZE);
*size *= sz;
*resident *= sz;
*share *= sz;
*trs *= sz;
*lrs *= sz;
*drs *= sz;
*dt *= sz;
*size /= 1024;
*resident /= 1024;
*share /= 1024;
*trs /= 1024;
*lrs /= 1024;
*drs /= 1024;
*dt /= 1024;
} else {
error("Failed to read sufficient fields from /proc/self/statm");
}
fclose(file);
} else {
error("Failed to open /proc/self/statm");
}
}
/**
* @brief Print the current memory use of the process. A la "top".
*/
void printProcMemUse() {
long size;
long resident;
long share;
long trs;
long lrs;
long drs;
long dt;
getProcMemUse(&size, &resident, &share, &trs, &lrs, &drs, &dt);
printf("## VIRT = %ld , RES = %ld , SHR = %ld , CODE = %ld, DATA = %ld\n",
size, resident, share, trs, drs);
fflush(stdout);
}
......@@ -44,4 +44,7 @@ void dumpMETISGraph(const char *prefix, idx_t nvtxs, idx_t ncon, idx_t *xadj,
void dumpCellRanks(const char *prefix, struct cell *cells_top, int nr_cells);
#endif
void getProcMemUse(long *size, long *resident, long *share, long *trs,
long *lrs, long *drs, long *dt);
void printProcMemUse();
#endif /* SWIFT_DEBUG_H */
......@@ -57,6 +57,7 @@
#include "error.h"
#include "gravity.h"
#include "hydro.h"
#include "map.h"
#include "minmax.h"
#include "parallel_io.h"
#include "part.h"
......@@ -898,6 +899,16 @@ void engine_repartition(struct engine *e) {
partition_repartition(e->reparttype, e->nodeID, e->nr_nodes, e->s,
e->sched.tasks, e->sched.nr_tasks);
/* Partitioning requires copies of the particles, so we need to reduce the
* memory in use to the minimum, we can free the sorting indices and the
* tasks as these will be regenerated at the next rebuild. */
/* Sorting indices. */
if (e->s->cells_top != NULL) space_free_cells(e->s);
/* Task arrays. */
scheduler_free_tasks(&e->sched);
/* Now comes the tricky part: Exchange particles between all nodes.
This is done in two steps, first allreducing a matrix of
how many particles go from where to where, then re-allocating
......
......@@ -966,9 +966,7 @@ void scheduler_reset(struct scheduler *s, int size) {
if (size > s->size) {
/* Free existing task lists if necessary. */
if (s->tasks != NULL) free(s->tasks);
if (s->tasks_ind != NULL) free(s->tasks_ind);
if (s->tid_active != NULL) free(s->tid_active);
scheduler_free_tasks(s);
/* Allocate the new lists. */
if (posix_memalign((void *)&s->tasks, task_align,
......@@ -1644,11 +1642,29 @@ void scheduler_print_tasks(const struct scheduler *s, const char *fileName) {
*/
void scheduler_clean(struct scheduler *s) {
free(s->tasks);
free(s->tasks_ind);
scheduler_free_tasks(s);
free(s->unlocks);
free(s->unlock_ind);
free(s->tid_active);
for (int i = 0; i < s->nr_queues; ++i) queue_clean(&s->queues[i]);
free(s->queues);
}
/**
* @brief Free the task arrays allocated by this #scheduler.
*/
void scheduler_free_tasks(struct scheduler *s) {
if (s->tasks != NULL) {
free(s->tasks);
s->tasks = NULL;
}
if (s->tasks_ind != NULL) {
free(s->tasks_ind);
s->tasks_ind = NULL;
}
if (s->tid_active != NULL) {
free(s->tid_active);
s->tid_active = NULL;
}
s->size = 0;
}
......@@ -143,5 +143,6 @@ void scheduler_set_unlocks(struct scheduler *s);
void scheduler_dump_queue(struct scheduler *s);
void scheduler_print_tasks(const struct scheduler *s, const char *fileName);
void scheduler_clean(struct scheduler *s);
void scheduler_free_tasks(struct scheduler *s);
#endif /* SWIFT_SCHEDULER_H */
......@@ -253,6 +253,15 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements,
}
}
/**
* @brief Free up any allocated cells.
*/
void space_free_cells(struct space *s) {
threadpool_map(&s->e->threadpool, space_rebuild_recycle_mapper,
s->cells_top, s->nr_cells, sizeof(struct cell), 0, s);
s->maxdepth = 0;
}
/**
* @brief Re-build the top-level cell grid.
*
......@@ -379,13 +388,15 @@ void space_regrid(struct space *s, int verbose) {
/* Free the old cells, if they were allocated. */
if (s->cells_top != NULL) {
threadpool_map(&s->e->threadpool, space_rebuild_recycle_mapper,
s->cells_top, s->nr_cells, sizeof(struct cell), 0, s);
space_free_cells(s);
free(s->cells_top);
free(s->multipoles_top);
s->maxdepth = 0;
}
/* Also free the task arrays, these will be regenerated and we can use the
* memory while copying the particle arrays. */
if (s->e != NULL) scheduler_free_tasks(&s->e->sched);
/* Set the new cell dimensions only if smaller. */
for (int k = 0; k < 3; k++) {
s->cdim[k] = cdim[k];
......@@ -492,9 +503,7 @@ void space_regrid(struct space *s, int verbose) {
else { /* Otherwise, just clean up the cells. */
/* Free the old cells, if they were allocated. */
threadpool_map(&s->e->threadpool, space_rebuild_recycle_mapper,
s->cells_top, s->nr_cells, sizeof(struct cell), 0, s);
s->maxdepth = 0;
space_free_cells(s);
}
if (verbose)
......
......@@ -226,5 +226,6 @@ void space_check_timesteps(struct space *s);
void space_replicate(struct space *s, int replicate, int verbose);
void space_reset_task_counters(struct space *s);
void space_clean(struct space *s);
void space_free_cells(struct space *s);
#endif /* SWIFT_SPACE_H */
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