bool power_layout_ready(void) { static time_t last_error_time = (time_t) 0; time_t now = time(NULL); struct node_record *node_ptr; uint32_t data[2]; int i; for (i = 0, node_ptr = node_record_table_ptr; i < node_record_count; i++, node_ptr++) { if (layouts_entity_get_mkv(L_NAME, node_ptr->name, "MaxWatts,IdleWatts", data, (sizeof(uint32_t) * 2), L_T_UINT32)) { /* Limit error message frequency, once per minute */ if (difftime(now, last_error_time) < 60) return false; last_error_time = now; error("%s: node %s is not in the layouts.d/power.conf file", __func__, node_ptr->name); return false; } } return true; }
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; }
extern int adapt_layouts(job_resources_t *job_resrcs_ptr, uint32_t cpu_freq_max, uint32_t node_id, char* node_name, bool new_value) { int i, k = 0, bit_inx = 0, core_cnt = 0; uint32_t max_watts, zero = 0, der; uint32_t core_num,val = 0; uint16_t num_freq; char temp[128], ename[128], keyname[128]; uint32_t data[2], vals[2]; int num_counts = 0, activate = 0; int *desalloc_cores; xassert(job_resrcs_ptr); for (i = 0; i < job_resrcs_ptr->nhosts; i++) { if (job_resrcs_ptr->sock_core_rep_count[i] <= node_id) { bit_inx += job_resrcs_ptr->sockets_per_node[i] * job_resrcs_ptr->cores_per_socket[i] * job_resrcs_ptr->sock_core_rep_count[i]; node_id -= job_resrcs_ptr->sock_core_rep_count[i]; } else { bit_inx += job_resrcs_ptr->sockets_per_node[i] * job_resrcs_ptr->cores_per_socket[i] * node_id; core_cnt = job_resrcs_ptr->sockets_per_node[i] * job_resrcs_ptr->cores_per_socket[i]; break; } } if (core_cnt < 1) { error("count_job_resources_node: core_cnt=0"); return 0; } i = bit_size(job_resrcs_ptr->core_bitmap); if ((bit_inx + core_cnt) > i) { error("count_job_resources_node: offset > bitmap size " "(%d >= %d)", (bit_inx + core_cnt), i); return 0; } layouts_entity_get_kv("power", node_name, "NumFreqChoices", &num_freq, L_T_UINT16); layouts_entity_get_mkv("power", node_name, "CoresCount,LastCore", data, (sizeof(uint32_t)*2),L_T_UINT32); if (cpu_freq_max != 0) { for (i = 1; i < num_freq + 1; i++) { sprintf(temp, "Cpufreq%d", i); layouts_entity_pullget_kv("power", node_name, temp, &val, L_T_UINT32); if (val == cpu_freq_max) { k = i; break; } } } desalloc_cores = xmalloc ( sizeof (int) * (core_cnt)); for (i = 0; i < core_cnt; i++) { /*core_num=LastCore+1-CoresCount*/ core_num = data[1] + 1 - data[0] + i; sprintf(ename, "virtualcore%u", core_num); if (bit_test(job_resrcs_ptr->core_bitmap, bit_inx++)) { if (new_value) { if (cpu_freq_max != 0 && k != 0) { sprintf(keyname, "Cpufreq%dWatts", k); layouts_entity_get_kv("power", ename, keyname, &max_watts, L_T_UINT32); } else { layouts_entity_get_kv("power", ename, "MaxCoreWatts", &max_watts, L_T_UINT32); } layouts_entity_set_kv("power", ename, "CurrentCorePower", &max_watts, L_T_UINT32); } else { layouts_entity_set_kv("power", ename, "CurrentCorePower", &zero, L_T_UINT32); desalloc_cores[num_counts] = i; num_counts++; } } else { layouts_entity_get_mkv("power", ename, "CurrentCorePower,IdleCoreWatts", vals, (sizeof(uint32_t)*2) ,L_T_UINT32); if (new_value) { if (vals[0] == 0) { layouts_entity_set_kv( "power", ename, "CurrentCorePower", &vals[1], L_T_UINT32); } } else { if (vals[1] != vals[0]) { activate = 1; } else { desalloc_cores[num_counts] = i; num_counts++; layouts_entity_set_kv( "power", ename, "CurrentCorePower", &zero, L_T_UINT32); layouts_entity_get_kv("power", ename, "CurrentCorePower", &der, L_T_UINT32); } } } } if (activate == 1) { for (i = 0; i < num_counts; i++) { core_num = data[1] + 1- data[0] + desalloc_cores[i]; sprintf(ename, "virtualcore%u", core_num); layouts_entity_set_kv("power", ename, "CurrentCorePower", &vals[1], L_T_UINT32); } } return 1; }