void rapl_finalize( struct rapl_state_s *s, int reset_limits){ int package; if(s->f == NULL){ printf("\n Error: File pointer should not be null. Something went wrong"); return; } if( s==NULL ){ printf("\n Error: State pointer should not be null. Something went wrong"); s = &no_caller_rapl_state; } if(s->initializedTick){ uint64_t tsc = rdtsc(); // require 10ms between ticks if(tsc_delta(&lastNonzeroTick, &tsc, &tsc_rate) > 0.01) rapl_tick(s, 0); } for(package=0; package<NUM_PACKAGES; package++){ get_all_status(package, s); if(reset_limits){ // Rest all limits. // This is currently the default limit on rzmerl. printf("\nRESETTING LIMITS\n"); write_msr( package, MSR_PKG_POWER_LIMIT, APPRO_DEFAULT_PKG_POWER_LIMIT); /* write_msr( package, MSR_PP0_POWER_LIMIT, 0 ); #ifdef ARCH_062D write_msr( package, MSR_DRAM_POWER_LIMIT, 0 ); #endif */ // These are currently locked out. //We had disabled turbo. The default is to leave this enabled. enable_turbo(package); } } // Now the print statement from hell. Call this only if it is not a dry-run //I.E., if we are in the read-only or the read-write modes. //Otherwise, the file should be empty. if(s->mode.dry_run_flag == 1 && s->mode.read_only_flag ==0 && s->mode.read_write_flag == 0){ fprintf(stdout, "\nIn DRY_RUN mode.\n"); finalize_msr(); } else { //This is either read-only or read_write mode. print_rapl_state(s); finalize_msr(); } }
void dump_stats(prof_t * prof) { uint32_t delta; delta = tsc_delta(prof->t1_upper, prof->t1_lower, prof->t2_upper, prof->t2_lower); delta -= noop_cycles; printf(" %u cycles (%g usec)\n", delta, ((double) delta / ((double) kHz * 1000.0)) * 1000000.0 ); }
void init_prof(prof_t * prof) { int i; FILE * fp; uint32_t olddelta; uint32_t delta; prof_t nothing; fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r"); if(fp == NULL) { fprintf(stderr, "Could not open cpuinfo from sysfs: %s\n", strerror(errno)); return; } fscanf(fp, "%u", &kHz); printf("DEBUG: detected %u MHz CPU\n", kHz / 1000); start_prof(¬hing); end_prof(¬hing); olddelta = tsc_delta(nothing.t1_upper, nothing.t1_lower, nothing.t2_upper, nothing.t2_lower); for(i = 0; i < 100; ++i) { start_prof(¬hing); end_prof(¬hing); delta = tsc_delta(nothing.t1_upper, nothing.t1_lower, nothing.t2_upper, nothing.t2_lower); if(delta != olddelta) { printf("DEBUG: cycle count for a no-op is changing!\n"); } olddelta = delta; } noop_cycles = delta; printf("DEBUG: noop cycles: %u\n", noop_cycles); fclose(fp); }
void msSample(const char * const filename, int log){ struct power_unit_s units; struct power_info_s info[NUM_DOMAINS]; double joules[NUM_DOMAINS]; uint64_t last_raw_joules[NUM_DOMAINS], last_raw_joules_tmp[NUM_DOMAINS]; struct timeval now; uint64_t tsc; double time = 0; #ifdef ARCH_062D int i; #endif double tsc_rate; FILE *rateFile = fopen("/tmp/tsc_rate", "r"); //! @todo measure/read tsc rate if(!rateFile && errno == ENOENT){ tsc_rate = measure_tsc(); rateFile = fopen("/tmp/tsc_rate", "w"); fprintf(rateFile, "%lf\n", tsc_rate); }else if(rateFile){ // get rate from file fscanf(rateFile, "%lf", &tsc_rate); } else { perror("error opening /tmp/tsc_rate"); exit(1); } fclose(rateFile); fprintf(stderr, "tsc rate: %lf\n", tsc_rate); FILE *logFile = 0; if(log){ logFile = fopen(filename, "w"); assert(logFile); } if(log){ fprintf(logFile, "timestamp\tpkg_J\tpp0_J\t" #ifdef ARCH_062A "pp1_J" #endif #ifdef ARCH_062D "dram_J" #endif "\n"); fprintf(logFile, "%lf\t%15.10lf\t%15.10lf" "\t%15.10lf" "\n", 0.0, 0.0, 0.0 #ifdef ARCH_062A ,0.0 #endif #ifdef ARCH_062D ,0.0 #endif ); } sigset_t s; sigemptyset(&s); sigaddset(&s, SIGALRM); struct sigaction sa = {.sa_handler= &handler, .sa_mask = s, .sa_flags = 0, .sa_restorer = 0}; int status = sigaction(SIGALRM, &sa, 0); timer_t timerID; status = timer_create(CLOCK_MONOTONIC, 0, &timerID); struct itimerspec ts = {{0, 100000}, // .1ms {0, 100000}}; msr_debug=1; get_rapl_power_unit(0, &units); get_power_info(0, PKG_DOMAIN, &info[PKG_DOMAIN],&units); msr_debug = 0; get_energy_status(0, PKG_DOMAIN, &joules[PKG_DOMAIN], &units, &last_raw_joules[PKG_DOMAIN]); get_energy_status(0, PKG_DOMAIN, &joules[PKG_DOMAIN], &units, &last_raw_joules[PKG_DOMAIN]); // synchronize with an update while(!joules[PKG_DOMAIN]){ usleep(10); get_energy_status(0, PKG_DOMAIN, &joules[PKG_DOMAIN], &units, &last_raw_joules[PKG_DOMAIN]); } gettimeofday(&now, NULL); tsc = rdtsc(); status = timer_settime(timerID, 0, &ts, 0); get_energy_status(0, PKG_DOMAIN, &joules[PKG_DOMAIN], &units, &last_raw_joules[PKG_DOMAIN]); get_energy_status(0, PP0_DOMAIN, &joules[PP0_DOMAIN], &units, &last_raw_joules[PP0_DOMAIN]); #ifdef ARCH_062D get_power_info(0, DRAM_DOMAIN, &info[DRAM_DOMAIN], &units); #endif #ifdef ARCH_062A get_energy_status(0, PP1_DOMAIN, &joules[PP1_DOMAIN], &units, &last_raw_joules[PP1_DOMAIN]); #endif double PKG_max_watts = 0, PP0_max_watts = 0; double PKG_total_joules = 0, PP0_total_joules = 0, delta; uint64_t lastPrint = 0, lastNonzero = tsc; int glitch = 0; while(1){ sigwaitinfo(&s, 0); // timer will wake us up tsc = rdtsc(); get_raw_energy_status(0, PKG_DOMAIN, &last_raw_joules_tmp[PKG_DOMAIN]); get_raw_energy_status(0, PP0_DOMAIN, &last_raw_joules_tmp[PP0_DOMAIN]); #ifdef ARCH_062A get_raw_energy_status(0, PP1_DOMAIN, &last_raw_joules_tmp[PP1_DOMAIN]); #endif #ifdef ARCH_062D get_raw_energy_status(0, DRAM_DOMAIN, &last_raw_joules_tmp[DRAM_DOMAIN]); #endif //! @todo freq //read_aperf_mperf(0, &aperf, &mperf); // wait for an update //! @todo this needs fixing if(last_raw_joules_tmp[PKG_DOMAIN] == last_raw_joules[PKG_DOMAIN]){ continue; } double nzDelta = tsc_delta(&lastNonzero, &tsc, &tsc_rate); if(nzDelta < .001){ // wait at least 1ms /*! @todo flag these in the log. Updates seem to come in two time bases, ~1 KHz and ~100 Hz. I'm guessing they correspond to distinct segments of the chip. If I sample frequently enough, I can separate the updates by frequency. */ if(!glitch){ /* fprintf(logFile, "#%lf\t%lf\tglitch \n", time + nzDelta, nzDelta ); */ glitch = 1; } last_raw_joules_tmp[PKG_DOMAIN] = last_raw_joules[PKG_DOMAIN]; continue; } glitch = 0; lastNonzero = tsc; // convert raw joules joules[PKG_DOMAIN] = convert_raw_joules_delta(&last_raw_joules[PKG_DOMAIN], &last_raw_joules_tmp[PKG_DOMAIN], &units); joules[PP0_DOMAIN] = convert_raw_joules_delta(&last_raw_joules[PP0_DOMAIN], &last_raw_joules_tmp[PP0_DOMAIN], &units); #ifdef ARCH_062A joules[PP1_DOMAIN] = convert_raw_joules_delta(&last_raw_joules[PP1_DOMAIN], &last_raw_joules_tmp[PP1_DOMAIN], &units); #endif #ifdef ARCH_062D joules[DRAM_DOMAIN] = convert_raw_joules_delta(&last_raw_joules[DRAM_DOMAIN], &last_raw_joules_tmp[DRAM_DOMAIN], &units); #endif last_raw_joules[PKG_DOMAIN] = last_raw_joules_tmp[PKG_DOMAIN]; last_raw_joules[PP0_DOMAIN] = last_raw_joules_tmp[PP0_DOMAIN]; #ifdef ARCH_062A last_raw_joules[PP1_DOMAIN] = last_raw_joules_tmp[PP1_DOMAIN]; #endif #ifdef ARCH_062D last_raw_joules[DRAM_DOMAIN] = last_raw_joules_tmp[DRAM_DOMAIN]; #endif time += nzDelta; // don't log the suspect readings // && joules[PKG_DOMAIN] < info[PKG_DOMAIN].thermal_spec_power_watts if(log){ fprintf(logFile, "%lf\t%15.10lf\t%15.10lf" "\t%15.10lf" "\n", time, joules[PKG_DOMAIN], joules[PP0_DOMAIN] #ifdef ARCH_062A ,joules[PP1_DOMAIN] #endif #ifdef ARCH_062D ,joules[DRAM_DOMAIN] #endif ); } PKG_max_watts = max(PKG_max_watts, joules[PKG_DOMAIN]/nzDelta); PP0_max_watts = max(PP0_max_watts, joules[PP0_DOMAIN]/nzDelta); PKG_total_joules += joules[PKG_DOMAIN]; PP0_total_joules += joules[PP0_DOMAIN]; delta = tsc_delta(&lastPrint, &tsc, &tsc_rate); if(delta > 1){ fprintf(stderr, "max 1ms-power, average power in last second: " "PKG: %10lf, %10lf, PP0: %10lf, %10lf\n", PKG_max_watts, PKG_total_joules / delta, PP0_max_watts, PP0_total_joules / delta); lastPrint = tsc; PKG_max_watts = 0; PP0_max_watts = 0; PKG_total_joules = 0; PP0_total_joules = 0; } } // while(1) //! @todo calculate average power return; }