Skip to main content

Manual Reconfiguration Control

DMR does not have a custom policy plugin interface yet. Instead, you implement reconfiguration logic directly in your application code and pass SHOULD_EXPAND, SHOULD_SHRINK, or SHOULD_STAY to dmr_check.

Basic pattern

while (should_keep_running()) {
DMRSuggestion suggestion = my_decide();
DMR_AUTO(dmr_check(suggestion), save(), (void)NULL, cleanup());
do_work();
}

my_decide() is plain application code. It reads DMR state, applies whatever logic fits your workload, and returns a suggestion.

Key functions for decision logic

FunctionDescription
dmr_get_current_node_count()Current node count in MPI_COMM_WORLD
dmr_get_reconfig_count()Number of reconfigurations since launch
dmr_get_active_expansions()Number of expansion jobs currently active
dmr_pending_expansion()1 if an expansion is pending
dmr_set_nodes_next_expand(n)Request n nodes in the next expand
dmr_set_nodes_next_shrink(n)Remove n nodes in the next shrink
dmr_cancel_expansion()Cancel a pending expansion (collective)

Example: phase-driven scaling

A common pattern is to scale based on the current phase of computation. Shrink before a communication-heavy phase, expand before a compute-heavy one:

typedef enum { PHASE_COMPUTE, PHASE_COMMUNICATE } Phase;

DMRSuggestion decide(Phase current_phase, int max_nodes, int min_nodes)
{
int nodes = dmr_get_current_node_count();

if (current_phase == PHASE_COMPUTE && nodes < max_nodes) {
dmr_set_nodes_next_expand(max_nodes - nodes);
return SHOULD_EXPAND;
}

if (current_phase == PHASE_COMMUNICATE && nodes > min_nodes) {
dmr_set_nodes_next_shrink(nodes - min_nodes);
return SHOULD_SHRINK;
}

return SHOULD_STAY;
}

Example: time-window scaling

In time-constrained environments you may want to request resources early and fall back to smaller requests as the deadline approaches. This is the strategy used in loop-qc:

/* Try to get max_nodes early in the window. As time runs out,
halve the target until it is no longer worth expanding.
Cancel any pending request that is being replaced. */
DMRSuggestion decide_by_window(int max_nodes, int min_nodes,
double elapsed_s, double window_s)
{
double remaining = window_s - elapsed_s;

if (remaining < 60.0) {
dmr_cancel_expansion();
return SHOULD_STAY;
}

int target = max_nodes;
double stage_end = 0.0;
double fraction = 0.5;

while (target >= min_nodes * 2) {
stage_end += window_s * fraction;

if (elapsed_s <= stage_end) {
int to_add = target - dmr_get_current_node_count();
if (to_add > 0) {
dmr_cancel_expansion();
dmr_set_nodes_next_expand(to_add);
return SHOULD_EXPAND;
}
return SHOULD_STAY;
}

target /= 2;
fraction /= 2;
}

return SHOULD_STAY;
}

Sizing the next operation

Override the number of nodes or processes for the next reconfiguration only. Values reset after each reconfiguration.

dmr_set_nodes_next_expand(int nodes);
dmr_set_procs_next_expand(int procs); // total processes across all new nodes
dmr_set_ppn_next_expand(int ppn); // processes per node
dmr_set_nodes_next_shrink(int nodes);
dmr_set_procs_next_shrink(int procs);
dmr_set_jobs_next_shrink(int jobs); // remove N whole expansion jobs

Cancelling a pending expansion

If conditions change and you no longer want a pending expansion:

if (dmr_pending_expansion()) {
dmr_cancel_expansion(); // collective, all ranks must call
}

Using the inhibitor

To rate-limit how often DMR attempts a reconfiguration regardless of the suggestion:

dmr_set_reconf_step_inhibitor(9); // 1 in every 10 calls is acted on
DMR_AUTO(dmr_check(SHOULD_EXPAND), save(), (void)NULL, cleanup());