Beispiel #1
0
void 
get_all_info(int package, struct rapl_state_s *s){
	if( s==NULL ){
		s = &no_caller_rapl_state;
	}
	get_rapl_power_unit( package, &(s->power_unit[package]) );
	get_power_info(    package, PKG_DOMAIN,  &(s->power_info[package][PKG_DOMAIN]),          &(s->power_unit[package]) );
#ifdef ARCH_062D
	get_power_info(    package, DRAM_DOMAIN, &(s->power_info[package][DRAM_DOMAIN]),         &(s->power_unit[package]) );
#endif
}
Beispiel #2
0
void dump_rapl_power_unit(FILE *writedest)
{
    int socket;
    struct rapl_units *r;
    static uint64_t sockets = 0;

    sockets = num_sockets();
    r = (struct rapl_units *) libmsr_calloc(sockets, sizeof(struct rapl_units));
    get_rapl_power_unit(r);

    for (socket = 0; socket < sockets; socket++)
    {
        fprintf(writedest, "Socket: %d\n", socket);
        fprintf(writedest, "   RAW power unit (W) = %8.4lf  energy unit (J^-1) = %8.4lf  time unit (s^-1) = %8.4lf\n", r[socket].watts, r[socket].joules, r[socket].seconds);
        fprintf(writedest, "   ADJ power unit (W) = %f  energy unit (J)    = %f    time unit (s)    = %f\n", r[socket].watts, 1/r[socket].joules, 1/r[socket].seconds);
    }
}
Beispiel #3
0
void
rapl_init(struct rapl_state_s *s, FILE *f, int print_header){
	int socket;
	init_msr();
	//parse_opts( argc, argv );
	//fprintf(stderr, "%s::%d returned from parse_opts\n", __FILE__, __LINE__);
	s->f = f;
	if(print_header)
	  print_rapl_state_header(s);

	for(socket=0; socket<NUM_PACKAGES; socket++){
		get_rapl_power_unit( socket, &(s->power_unit[socket]) );
		get_power_info(    socket, PKG_DOMAIN,  &(s->power_info[socket][PKG_DOMAIN]),          &(s->power_unit[socket]) );
#ifdef ARCH_062D
		get_power_info(    socket, DRAM_DOMAIN, &(s->power_info[socket][DRAM_DOMAIN]),         &(s->power_unit[socket]) );
#endif

		get_power_limit(   socket, PKG_DOMAIN,  &(s->power_limit[socket][PKG_DOMAIN]),         &(s->power_unit[socket]) );
		get_power_limit(   socket, PP0_DOMAIN,  &(s->power_limit[socket][PP0_DOMAIN]),         &(s->power_unit[socket]) );
#ifdef ARCH_062D
		get_power_limit(   socket, DRAM_DOMAIN, &(s->power_limit[socket][DRAM_DOMAIN]),        &(s->power_unit[socket]) );
#endif

		get_energy_status( socket, PKG_DOMAIN,  NULL, 
				   &(s->power_unit[socket]),
				   &s->last_raw_joules[socket][PKG_DOMAIN]);
		get_energy_status( socket, PP0_DOMAIN,  NULL, 
				   &(s->power_unit[socket]) ,
				   &s->last_raw_joules[socket][PP0_DOMAIN]);
#ifdef ARCH_062D
		get_energy_status( socket, DRAM_DOMAIN, NULL, 
				   &(s->power_unit[socket]) ,
				   &s->last_raw_joules[socket][DRAM_DOMAIN]);
#endif
	}
	gettimeofday( &(s->prev), NULL );
}
Beispiel #4
0
/// @brief Translate any user-desired values to the format expected in the MSRs
/// and vice versa.
///
/// @param [in] socket Unique socket/package identifier.
///
/// @param [out] bits Raw bit field value.
///
/// @param [out] units Human-readable value.
///
/// @param [in] type libmsr_unit_conversions_e unit conversion identifier.
///
/// @return 0 upon function completion or upon converting bits to Joules for
/// DRAM RAPL power domain for 0x3F (Haswell) platform.
static int translate(const unsigned socket, uint64_t *bits, double *units, int type)
{
    static int init = 0;
    double logremainder = 0.0;
    static uint64_t sockets = 0;
    static uint64_t model = 0;
    static struct rapl_units *ru = NULL;
    uint64_t timeval_z = 0;
    uint64_t timeval_y = 0;

#ifdef LIBMSR_DEBUG
    fprintf(stderr, "DEBUG: (translate) bits are at %p\n", bits);
#endif
    if (sockets == 0)
    {
        sockets = num_sockets();
    }
    if (model == 0)
    {
        cpuid_get_model(&model);
    }
    sockets_assert(&socket, __LINE__, __FILE__);

    if (!init)
    {
        init = 1;
        ru = (struct rapl_units *) libmsr_calloc(sockets, sizeof(struct rapl_units));
        get_rapl_power_unit(ru);
    }
    switch(type)
    {
        case BITS_TO_WATTS:
            *units = (double)(*bits) * ru[socket].watts;
            break;
        case BITS_TO_JOULES_DRAM:
            if (model == 0x3F || model == 0x4F || model == 0x55)
            {
                *units = (double)(*bits) / STD_ENERGY_UNIT;
#ifdef LIBMSR_DEBUG
                fprintf(stderr, "DEBUG: (translate_dram) %f is %f joules\n", (double)*bits, *units);
#endif
                return 0;
            }
            /* No break statement, if not Haswell do standard stuff. */
        case BITS_TO_JOULES:
            *units = (double)(*bits) / ru[socket].joules;
            break;
        case WATTS_TO_BITS:
            *bits  = (uint64_t)((*units) / ru[socket].watts);
            break;
        case JOULES_TO_BITS:
            /// @todo Currently unused, but if it ever is used, we need a fix for Haswell.
            *bits  = (uint64_t)((*units) * ru[socket].joules);
            break;
        case BITS_TO_SECONDS_STD:
            timeval_y = *bits & 0x1F;
            timeval_z = (*bits & 0x60) >> 5;
            /* Dividing by time unit because it's stored as (1/(2^TU))^-1. */
            *units = ((1 + 0.25 * timeval_z) * pow(2.0,(double)timeval_y)) / ru[socket].seconds;
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units * 2.5 + 15.0;
            //    }
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits);
#endif
            break;
        case SECONDS_TO_BITS_STD:
            // Temporary fix for haswell
            //    if (model == 0x3F)
            //    {
            //        *units = *units / 2.5 - 15;
            //    }
            /* Store the whole number part of the log2. */
            timeval_y = (uint64_t)log2(*units * ru[socket].seconds);
            /* Store the mantissa of the log2. */
            logremainder = (double)log2(*units * ru[socket].seconds) - (double)timeval_y;
            timeval_z = 0;
            /* Based on the mantissa, choose the appropriate multiplier. */
            if (logremainder > 0.15 && logremainder <= 0.45)
            {
                timeval_z = 1;
            }
            else if (logremainder > 0.45 && logremainder <= 0.7)
            {
                timeval_z = 2;
            }
            else if (logremainder > 0.7)
            {
                timeval_z = 3;
            }
            /* Store the bits in the Intel specified format. */
            *bits = (uint64_t)(timeval_y | (timeval_z << 5));
#ifdef LIBMSR_DEBUG
            fprintf(stderr, "%s %s::%d DEBUG: timeval_z is %lx, timeval_y is %lx, units is %lf, bits is %lx, remainder is %lf\n", getenv("HOSTNAME"), __FILE__, __LINE__, timeval_z, timeval_y, *units, *bits, logremainder);
#endif
            break;
        default:
            fprintf(stderr, "%s:%d  Unknown value %d.  This is bad.\n", __FILE__, __LINE__, type);
            *bits = -1;
            *units= -1.0;
            break;
    }
    return 0;
}
Beispiel #5
0
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;
}