void realloc_cells(int size) { int i; CELL_TRACE(fprintf(stderr, "%d: realloc_cells %d\n", this_node, size)); /* free all memory associated with cells to be deleted. */ for(i=size; i<n_cells; i++) { realloc_particlelist(&cells[i],0); } /* resize the cell list */ if(size != n_cells) { cells = (Cell *) realloc(cells, sizeof(Cell)*size); } /* initialize new cells */ for(i=n_cells; i<size; i++) { init_particlelist(&cells[i]); } n_cells = size; }
void nsq_balance_particles() { int i, n, surplus, s_node, tmp, lack, l_node, transfer; int pp = cells_get_n_particles(); int *ppnode = malloc(n_nodes*sizeof(int)); /* minimal difference between node shares */ int minshare = n_total_particles/n_nodes; int maxshare = minshare + 1; CELL_TRACE(fprintf(stderr, "%d: nsq_balance_particles: load %d-%d\n", this_node, minshare, maxshare)); MPI_Allgather(&pp, 1, MPI_INT, ppnode, 1, MPI_INT, MPI_COMM_WORLD); for (;;) { /* find node with most excessive particles */ surplus = -1; s_node = -1; for (n = 0; n < n_nodes; n++) { tmp = ppnode[n] - minshare; CELL_TRACE(fprintf(stderr, "%d: nsq_balance_particles: node %d has %d\n", this_node, n, ppnode[n])); if (tmp > surplus) { surplus = tmp; s_node = n; } } CELL_TRACE(fprintf(stderr, "%d: nsq_balance_particles: excess %d on node %d\n", this_node, surplus, s_node)); /* find node with most lacking particles */ lack = -1; l_node = -1; for (n = 0; n < n_nodes; n++) { tmp = maxshare - ppnode[n]; if (tmp > lack) { lack = tmp; l_node = n; } } CELL_TRACE(fprintf(stderr, "%d: nsq_balance_particles: lack %d on node %d\n", this_node, lack, l_node)); /* should not happen: minshare or maxshare wrong or more likely, the algorithm */ if (s_node == -1 || l_node == -1) { fprintf(stderr, "%d: Particle load balancing failed\n", this_node); break; } /* exit if all nodes load is withing min and max share */ if (lack <= 1 && surplus <= 1) break; transfer = lack < surplus ? lack : surplus; if (s_node == this_node) { ParticleList send_buf; init_particlelist(&send_buf); realloc_particlelist(&send_buf, send_buf.n = transfer); for (i = 0; i < transfer; i++) { memcpy(&send_buf.part[i], &local->part[--local->n], sizeof(Particle)); } realloc_particlelist(local, local->n); update_local_particles(local); send_particles(&send_buf, l_node); #ifdef ADDITIONAL_CHECKS check_particle_consistency(); #endif } else if (l_node == this_node) { recv_particles(local, s_node); #ifdef ADDITIONAL_CHECKS check_particle_consistency(); #endif } ppnode[s_node] -= transfer; ppnode[l_node] += transfer; } CELL_TRACE(fprintf(stderr, "%d: nsq_balance_particles: done\n", this_node)); free(ppnode); }