int powercap_get_job_optimal_cpufreq(uint32_t powercap, int *allowed_freqs) { uint32_t cur_max_watts = 0, *tmp_max_watts_dvfs = NULL; int k = 1; bitstr_t *tmp_bitmap = NULL; if (!_powercap_enabled()) return 0; tmp_max_watts_dvfs = xmalloc(sizeof(uint32_t) * (allowed_freqs[0]+1)); tmp_bitmap = bit_copy(idle_node_bitmap); bit_not(tmp_bitmap); cur_max_watts = powercap_get_node_bitmap_maxwatts_dvfs(tmp_bitmap, idle_node_bitmap,tmp_max_watts_dvfs,allowed_freqs,0); if (cur_max_watts > powercap) { while (tmp_max_watts_dvfs[k] > powercap && k < allowed_freqs[0] + 1) { k++; } if (k == allowed_freqs[0] + 1) k--; } else k = 1; return k; }
uint32_t powercap_get_cluster_adjusted_max_watts(void) { uint32_t adj_max_watts = 0,val; struct node_record *node_ptr; int i; if (!_powercap_enabled()) return 0; if (!power_layout_ready()) return 0; for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { if (bit_test(power_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_SAVE, &val, L_T_UINT32); } else if (!bit_test(up_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_DOWN, &val, L_T_UINT32); } else { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_MAX, &val, L_T_UINT32); } adj_max_watts += val; } return adj_max_watts; }
uint32_t powercap_get_cluster_min_watts(void) { uint32_t min_watts = 0, tmp_watts, save_watts, down_watts; struct node_record *node_ptr; int i; if (!_powercap_enabled()) return 0; if (!power_layout_ready()) return 0; for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_IDLE, &tmp_watts, L_T_UINT32); layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_DOWN, &down_watts, L_T_UINT32); tmp_watts = MIN(tmp_watts, down_watts); layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_SAVE, &save_watts, L_T_UINT32); tmp_watts = MIN(tmp_watts, save_watts); min_watts += tmp_watts; } return min_watts; }
int which_power_layout(void) { int p, k; if (!_powercap_enabled()) return 0; p = _which_power_layout("power"); k = _which_power_layout("power_cpufreq"); if ((p) && (k)) return 0; else if (p == 0) { slurm_mutex_lock(&powercap_mutex); if (!l_name) l_name = xstrdup("power"); slurm_mutex_unlock(&powercap_mutex); return 1; } else if (k == 0) { slurm_mutex_lock(&powercap_mutex); if (!l_name) l_name = xstrdup("power_cpufreq"); slurm_mutex_unlock(&powercap_mutex); return 2; } return 0; }
int* powercap_get_job_nodes_numfreq(bitstr_t *select_bitmap, uint32_t cpu_freq_min, uint32_t cpu_freq_max) { uint16_t num_freq = 0; int i, p, *allowed_freqs = NULL, new_num_freq = 0; struct node_record *node_ptr; char ename[128]; uint32_t cpufreq; if (!_powercap_enabled()) return 0; if ((cpu_freq_min == NO_VAL) && (cpu_freq_max == NO_VAL)) { allowed_freqs = xmalloc(sizeof(int) * 2); /* allowed_freqs[0] = 0; Default value */ return allowed_freqs; } for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { if (bit_test(select_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NUM_FREQ, &num_freq, L_T_UINT16); allowed_freqs = xmalloc(sizeof(int)*((int)num_freq+2)); allowed_freqs[-1] = (int) num_freq; for (p = num_freq; p > 0; p--) { sprintf(ename, "Cpufreq%d", p); layouts_entity_pullget_kv(L_NAME, node_ptr->name, ename, &cpufreq, L_T_UINT32); /* In case a job is submitted with flags Low,High, etc on * --cpu-freq parameter then we consider the whole range * of available frequencies on nodes */ if (((cpu_freq_min <= cpufreq) && (cpufreq <= cpu_freq_max)) || ((cpu_freq_min & CPU_FREQ_RANGE_FLAG) || (cpu_freq_max & CPU_FREQ_RANGE_FLAG))) { new_num_freq++; allowed_freqs[new_num_freq] = p; } } break; } } if (allowed_freqs) { allowed_freqs[0] = new_num_freq; } else { allowed_freqs = xmalloc(sizeof(int) * 2); /* allowed_freqs[0] = 0; Default value */ } return allowed_freqs; }
uint32_t powercap_get_node_bitmap_maxwatts(bitstr_t *idle_bitmap) { uint32_t max_watts = 0, val; struct node_record *node_ptr; int i; bitstr_t *tmp_bitmap = NULL; if (!_powercap_enabled()) return 0; if (!power_layout_ready()) return 0; /* if no input bitmap, consider the current idle nodes * bitmap as the input bitmap tagging nodes to consider * as idle while computing the max watts of the cluster */ if (idle_bitmap == NULL) { tmp_bitmap = bit_copy(idle_node_bitmap); idle_bitmap = tmp_bitmap; } for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { /* non reserved node, evaluate the different cases */ if (bit_test(idle_bitmap, i)) { /* idle nodes, 2 cases : power save or not */ if (bit_test(power_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_SAVE, &val, L_T_UINT32); } else { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_IDLE, &val, L_T_UINT32); } } else { /* non idle nodes, 2 cases : down or not */ if (!bit_test(up_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_DOWN, &val, L_T_UINT32); } else { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_MAX, &val, L_T_UINT32); } } max_watts += val; } if (tmp_bitmap) bit_free(tmp_bitmap); return max_watts; }
uint32_t powercap_get_cluster_max_watts(void) { uint32_t max_watts; if (!_powercap_enabled()) return 0; if (!power_layout_ready()) return 0; layouts_entity_pullget_kv(L_NAME, L_CLUSTER, L_SUM_MAX, &max_watts, L_T_UINT32); return max_watts; }
int which_power_layout(void) { layout_t* layout; if (!_powercap_enabled()) return 0; layout = layouts_get_layout("power"); if (layout == NULL) return 0; else if (strcmp(layout->name,"default") == 0) return 1; else if (strcmp(layout->name,"cpufreq") == 0) return 2; return 0; }
uint32_t powercap_get_cluster_current_max_watts(void) { uint32_t cur_max_watts = 0; if (!_powercap_enabled()) return 0; if (!power_layout_ready()) return 0; if (which_power_layout() == 1) { cur_max_watts = powercap_get_node_bitmap_maxwatts(NULL); } else { cur_max_watts = powercap_get_node_bitmap_maxwatts_dvfs( NULL, NULL, NULL, 0, 0); } return cur_max_watts; }
uint32_t powercap_get_cpufreq(bitstr_t *select_bitmap, int k) { int i; struct node_record *node_ptr; char ename[128]; uint32_t cpufreq = 0; if (!_powercap_enabled()) return cpufreq; for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { if (bit_test(select_bitmap, i)) { sprintf(ename, "Cpufreq%d", k); layouts_entity_pullget_kv(L_NAME, node_ptr->name, ename, &cpufreq, L_T_UINT32); } break; } return cpufreq; }
uint32_t powercap_get_node_bitmap_maxwatts_dvfs(bitstr_t *idle_bitmap, bitstr_t *select_bitmap, uint32_t *max_watts_dvfs, int* allowed_freqs, uint32_t num_cpus) { uint32_t max_watts = 0, tmp_max_watts = 0, val = 0; uint32_t *tmp_max_watts_dvfs = NULL; struct node_record *node_ptr; int i, p; char ename[128], keyname[128]; bitstr_t *tmp_bitmap = NULL; uint32_t data[5], core_data[4]; if (!_powercap_enabled()) return 0; if (max_watts_dvfs != NULL) { tmp_max_watts_dvfs = xmalloc(sizeof(uint32_t)*(allowed_freqs[0]+1)); } /* if no input bitmap, consider the current idle nodes * bitmap as the input bitmap tagging nodes to consider * as idle while computing the max watts of the cluster */ if (idle_bitmap == NULL && select_bitmap == NULL) { tmp_bitmap = bit_copy(idle_node_bitmap); idle_bitmap = tmp_bitmap; select_bitmap = tmp_bitmap; } for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { if (bit_test(idle_bitmap, i)) { /* idle nodes, 2 cases : power save or not */ if (bit_test(power_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_SAVE, &val, L_T_UINT32); } else { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_IDLE, &val, L_T_UINT32); } } else if (bit_test(select_bitmap, i)) { layouts_entity_get_mkv(L_NAME, node_ptr->name, "IdleWatts,MaxWatts,CoresCount,LastCore,CurrentPower", data, (sizeof(uint32_t) * 5), L_T_UINT32); /* tmp_max_watts = IdleWatts - cpus*IdleCoreWatts * + cpus*MaxCoreWatts */ sprintf(ename, "virtualcore%u", data[3]); if (num_cpus == 0) num_cpus = data[2]; layouts_entity_get_mkv(L_NAME, ename, "IdleCoreWatts,MaxCoreWatts", core_data, (sizeof(uint32_t) * 2), L_T_UINT32); if (data[4] == 0) { tmp_max_watts += data[0] - num_cpus*core_data[0] + num_cpus*core_data[1]; } else if (data[4] > 0) { tmp_max_watts += data[4] - num_cpus*core_data[0] + num_cpus*core_data[1]; } else if (num_cpus == data[2]) tmp_max_watts += data[1]; if (!tmp_max_watts_dvfs) goto skip_dvfs; for (p = 1; p < (allowed_freqs[0] + 1); p++) { sprintf(keyname, "IdleCoreWatts,MaxCoreWatts," "Cpufreq%dWatts,CurrentCorePower", allowed_freqs[p]); layouts_entity_get_mkv(L_NAME, ename, keyname, core_data, (sizeof(uint32_t) * 4), L_T_UINT32); if (num_cpus == data[2]) { tmp_max_watts_dvfs[p] += num_cpus*core_data[2]; } else { if (data[4] == 0) { tmp_max_watts_dvfs[p] += data[0] - num_cpus*core_data[0] + num_cpus*core_data[2]; } else { tmp_max_watts_dvfs[p] += data[4] - num_cpus*core_data[0] + num_cpus*core_data[2]; } } } skip_dvfs: ; } else { /* non-idle nodes, 2 cases : down or not */ if (!bit_test(up_node_bitmap, i)) { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_DOWN, &val, L_T_UINT32); } else { layouts_entity_pullget_kv(L_NAME, node_ptr->name, L_NODE_CUR, &val, L_T_UINT32); } } max_watts += val; val = 0; } if (max_watts_dvfs) { for (p = 1; p < allowed_freqs[0] + 1; p++) { max_watts_dvfs[p] = max_watts + tmp_max_watts_dvfs[p]; } xfree(tmp_max_watts_dvfs); } max_watts += tmp_max_watts; if (tmp_bitmap) bit_free(tmp_bitmap); return max_watts; }