/* * Validate the cpus and select the frequency to set * Called from task cgroup cpuset code with string containing * the list of cpus to be used by this step */ extern void cpu_freq_cgroup_validate(stepd_step_rec_t *job, char *step_alloc_cores) { uint16_t start = USHRT_MAX; uint16_t end = USHRT_MAX; uint16_t cpuidx = 0; char *core_range; debug_flags = slurm_get_debug_flags(); /* init for slurmstepd */ if (debug_flags & DEBUG_FLAG_CPU_FREQ) { info("cpu_freq_cgroup_validate: request: min=(%12d %8x) " "max=(%12d %8x) governor=%8x", job->cpu_freq_min, job->cpu_freq_min, job->cpu_freq_max, job->cpu_freq_max, job->cpu_freq_gov); info(" jobid=%u, stepid=%u, tasks=%u cpu/task=%u, cpus=%u", job->jobid,job->stepid,job->node_tasks, job->cpus_per_task,job->cpus); info(" cpu_bind_type=%4x, cpu_bind map=%s", job->cpu_bind_type, job->cpu_bind); info(" step logical cores = %s, step physical cores = %s", job->step_alloc_cores, step_alloc_cores); } if (!cpu_freq_count) return; for (cpuidx = 0; cpuidx < cpu_freq_count; cpuidx++) { _cpu_freq_init_data(cpuidx); } /* set entries in cpu frequency table for this step's cpus */ core_range = step_alloc_cores; while ( (cpuidx = _cpu_freq_next_cpu(&core_range, &cpuidx, &start, &end)) != USHRT_MAX) { if (cpuidx >= cpu_freq_count) { error("cpu_freq_validate: index %u exceeds cpu count %u", cpuidx, cpu_freq_count); return; } _cpu_freq_setup_data(job, cpuidx); } cpu_freq_set(job); return; }
/* * Validate the cpus and select the frequency to set * Called from task cpuset code with task launch request containing * a pointer to a hex map string of the cpus to be used by this step */ extern void cpu_freq_cpuset_validate(stepd_step_rec_t *job) { int cpuidx, cpu_num; bitstr_t *cpus_to_set; bitstr_t *cpu_map; char *cpu_bind; char *cpu_str; char *savestr = NULL; debug_flags = slurm_get_debug_flags(); /* init for slurmstepd */ if (debug_flags & DEBUG_FLAG_CPU_FREQ) { info("cpu_freq_cpuset_validate: request: min=(%12d %8x) " "max=(%12d %8x) governor=%8x", job->cpu_freq_min, job->cpu_freq_min, job->cpu_freq_max, job->cpu_freq_max, job->cpu_freq_gov); info(" jobid=%u, stepid=%u, tasks=%u cpu/task=%u, cpus=%u", job->jobid, job->stepid, job->node_tasks, job->cpus_per_task, job->cpus); info(" cpu_bind_type=%4x, cpu_bind map=%s", job->cpu_bind_type, job->cpu_bind); } if (!cpu_freq_count) return; if (job->cpu_bind == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string is null"); return; } cpu_bind = xstrdup(job->cpu_bind); if ( (cpu_str = strtok_r(cpu_bind, ",", &savestr) ) == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string invalid"); xfree(cpu_bind); return; } cpu_map = (bitstr_t *) bit_alloc(cpu_freq_count); cpus_to_set = (bitstr_t *) bit_alloc(cpu_freq_count); do { debug3(" cpu_str = %s", cpu_str); if ((job->cpu_bind_type & CPU_BIND_MAP) == CPU_BIND_MAP) { cpu_num = atoi(cpu_str); if (cpu_num >= cpu_freq_count) { error("cpu_freq_cpuset_validate: invalid cpu " "number %d", cpu_num); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } bit_set(cpu_map, (bitoff_t)cpu_num); } else { if (bit_unfmt_hexmask(cpu_map, cpu_str) == -1) { error("cpu_freq_cpuset_validate: invalid cpu " "mask %s", cpu_bind); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } } bit_or(cpus_to_set, cpu_map); } while ( (cpu_str = strtok_r(NULL, ",", &savestr) ) != NULL); for (cpuidx = 0; cpuidx < cpu_freq_count; cpuidx++) { _cpu_freq_init_data(cpuidx); if (bit_test(cpus_to_set, cpuidx)) { _cpu_freq_setup_data(job, cpuidx); } } cpu_freq_set(job); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; }
/* * called to check if the node supports setting CPU frequency * if so, initialize fields in cpu_freq_data structure */ extern void cpu_freq_init(slurmd_conf_t *conf) { char path[PATH_MAX]; struct stat statbuf; FILE *fp; char value[LINE_LEN]; unsigned int i, j; debug_flags = slurm_get_debug_flags(); /* init for slurmd */ xfree(slurmd_spooldir); slurmd_spooldir = xstrdup(conf->spooldir); if (run_in_daemon("slurmstepd")) return; /* check for cpufreq support */ if ( stat(PATH_TO_CPU "cpu0/cpufreq", &statbuf) != 0 ) { info("CPU frequency setting not configured for this node"); return; } if (!S_ISDIR(statbuf.st_mode)) { error(PATH_TO_CPU "cpu0/cpufreq not a directory"); return; } /* get the cpu frequency info into the cpu_freq_data structure */ cpu_freq_count = conf->block_map_size; if (!cpufreq) { int cpuidx; cpufreq = (struct cpu_freq_data *) xmalloc(cpu_freq_count * sizeof(struct cpu_freq_data)); for (cpuidx = 0; cpuidx < cpu_freq_count; cpuidx++) _cpu_freq_init_data(cpuidx); } debug2("Gathering cpu frequency information for %u cpus", cpu_freq_count); for (i = 0; i < cpu_freq_count; i++) { snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/scaling_available_governors", i); if ((fp = fopen(path, "r")) == NULL) continue; if (fgets(value, LINE_LEN, fp) == NULL) { fclose(fp); continue; } if (strstr(value, "conservative")) { cpufreq[i].avail_governors |= GOV_CONSERVATIVE; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { info("cpu_freq: Conservative governor " "defined on cpu 0"); } } if (strstr(value, "ondemand")) { cpufreq[i].avail_governors |= GOV_ONDEMAND; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { info("cpu_freq: OnDemand governor " "defined on cpu 0"); } } if (strstr(value, "performance")) { cpufreq[i].avail_governors |= GOV_PERFORMANCE; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { info("cpu_freq: Performance governor " "defined on cpu 0"); } } if (strstr(value, "powersave")) { cpufreq[i].avail_governors |= GOV_POWERSAVE; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { info("cpu_freq: PowerSave governor " "defined on cpu 0"); } } if (strstr(value, "userspace")) { cpufreq[i].avail_governors |= GOV_USERSPACE; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { info("cpu_freq: UserSpace governor " "defined on cpu 0"); } } fclose(fp); if (_cpu_freq_cpu_avail(i) == SLURM_FAILURE) continue; if ((i == 0) && (debug_flags & DEBUG_FLAG_CPU_FREQ)) { for (j = 0; j < cpufreq[i].nfreq; j++) { info("cpu_freq: frequency %u defined on cpu 0", cpufreq[i].avail_freq[j]); } } } return; }