Using the Intel Power Gadget API on Mac OS X

ID 777780
Updated 12/13/2012
Version Latest
Public

author-image

By

Using the Intel® Power Gadget API on Mac OS X*

Intel® Power Gadget for Mac* is a GUI application that provides real-time data on processor frequency and estimated processor power, and can log frequency, power, energy, and temperature data over time. Intel® Power Gadget also provides a C Application Programming Interface (API) for accessing this power and frequency data in your program. Intel® Power Gadget is also available for Windows* and Linux*. Intel® Power Gadget and the API are only supported on 2nd generation and later Intel® Core processors, because previous processors do not support the necessary power Model Specific Registers (MSRs).

Intro to the Intel® Power Gadget API

The Intel® Power Gadget API is a framework (IntelPowerGadget .framework) that provides a C interface for reading current estimated processor power, current processor frequency, base frequency, thermal design power (TDP), current temperature, maximum temperature, timestamps, and elapsed time. It also provides logging functionality.

What You Need

To use the API you’ll need the Intel® Power Gadget for Mac* driver and framework. These are included in the Intel® Power Gadget installer, or as a standalone API installer. The driver is installed to /System/Library/Extensions/EnergyDriver.kext, and the framework is installed to /Library/Frameworks/IntelPowerGadget.framework.

To link with the Intel® Power Gadget API you simply need to include
–framework IntelPowerGadget in your link command.

Using the Intel® Power Gadget API

To begin you must initialize the library by calling IntelEnergyLibInitialize.

The most common use of the Intel® Power Gadget API is to read samples with ReadSample. The API supports sampling of specific Model Specific Registers (MSRs). Meta data on the sampled MSRs can be queried with GetNumMsrs, GetMsrName, and GetMsrFunc. GetNumMsrs returns the number of sampled MSRs; MSRs are given an ID from 0 to n-1, where n is the number returned by GetNumMsrs. The MSR ID is used to get data for a specific MSR with functions GetPowerData, GetMsrName, and GetMsrFunc.

Calling GetPowerData for each sampled MSR will provide you with the relevant data from that MSR. An MSR’s function (from GetMsrFunc) determines the amount and meaning of data returned from GetPowerData. MSRs with function 0 (frequency) return 1 result, which represents the frequency in megahertz. MSRs with function 1 (power) return 3 results, which represent the average power in watts, cumulative energy in Joules, and cumulative energy in milliwatt-hours. MSRs with function 2 (temperature) return 1 result, which represents the temperature in degrees Celsius. The Intel® Power Gadget API currently supports sampling with the following MSRs: processor frequency, estimated processor power, and package temperature. The currently supported MSR functions are: frequency (0), power (1), temperature (2).

ReadSample also reads the system time and Time Stamp Counter (TSC) at the time the sample is read. These values are available via GetSysTime and GetRDTSC; the time interval between samples is available (in seconds) via GetTimeInterval. Note that you must call ReadSample prior to calling GetPowerData, GetRDTSC, and GetTimeInterval, and that you must call ReadSample twice before calling GetTimeInterval and before getting power data (as opposed to frequency or temperature data) from GetPowerData, as they are computed using the difference between two samples.

The Intel® Power Gadget API also supports reading generic MSRs with ReadMSR, which returns the raw data from the MSR. However, note that specifying an invalid MSR address can crash your system and could potentially corrupt it. There is no method to determine if an MSR address is valid. The API supports reading common individual MSRs without having to specify the MSR address or read an entire sample; the supported functions are: GetIAFrequency, GetMaxTemperature, GetTemperature, and GetTDP.

The sample data from ReadSample can be logged to a file. Logging can be enabled at any time by calling StartLog, and subsequently disabled by calling StopLog. Note that the logged data isn’t written until StopLog is called. Both StartLog and StopLog cause an internal call to ReadSample.

Sampling Considerations

The frequency at which you read samples may have an impact on the accuracy of data. The instantaneous processor frequency can change significantly from moment to moment. Frequency data may be more meaningful if you sample often and average the frequency samples over time. The processor power is calculated by taking the difference between two samples, thus a shorter interval between samples will result in more fine-grained power data. However, the frequency at which you read samples may also impact the performance of the system. Using a very short frequency (e.g. less than 20 milliseconds) may result in significant overhead, and may also increase the power consumption of the system, both of which may reduce the usefulness of the data. The Intel® Power Gadget application uses a default sampling frequency of 50 milliseconds, and updates the GUI with averaged frequency and power data every second.

Example



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <IntelPowerGadget/EnergyLib.h>

int main(int argc, char* argv[]) {

	IntelEnergyLibInitialize();
	StartLog("/tmp/PowerGadgetLog.csv"); // causes a sample to be read
	
	int numMsrs = 0;
	GetNumMsrs(&numMsrs);
	
	for (int i = 0; i < 10; i++) {
		
		sleep(1);
		ReadSample();
		
		for (int j = 0; j < numMsrs; j++) {
			int funcID;
			char szName[1024];
			GetMsrFunc(j, &funcID);
			GetMsrName(j, szName);
			
			int nData;
			double data[3];
			GetPowerData(0, j, data, &nData);
			
			// Frequency
			if (funcID == MSR_FUNC_FREQ) {
				printf("%s = %4.0f", szName, data[0]);
			}
			
			// Power
			else if (funcID == MSR_FUNC_POWER) {
				printf(", %s Power (W) = %3.2f", szName, data[0]);
				printf(", %s Energy(J) = %3.2f", szName, data[1]);
				printf(", %s Energy(mWh)=%3.2f", szName, data[2]);
			}
			
			// Temperature
			else if (funcID == MSR_FUNC_TEMP) {
				printf(", %s Temp (C) = %3.0f", szName, data[0]);
			}
		}
		printf("\n");
	}
	
	sleep(1);
	StopLog();// causes a sample to be read
	
	return 0;
}

Download the Xcode project for this example application here.

API Reference

int IntelEnergyLibInitialize();

Initializes the library and connects to the driver.

int GetNumNodes(int *nNodes);

Returns the number of CPU packages on the system.

int GetNumMsrs(int *nMsr);

Returns the number of supported MSRs for bulk reading and logging.

int GetMsrName(int iMsr, char *szName);

Returns in szName the name of the MSR specified by iMsr. Note that the Windows version uses wchar_t.

int GetMsrFunc(int iMsr, int *pFuncID);

Returns in pFuncID the function of the MSR specified by iMsrCurrently supported functions are: 0 = frequency, 1 = power, 2 = temperature.

int ReadMSR(int iNode, unsigned int address, uint64_t *value);

Reads the MSR specified by address on the package specified by iNode, and returns the value in value. Warning: Specifying an invalid MSR address can crash your system and could potentially corrupt it. There is no method to determine if an MSR address is valid.

int GetIAFrequency(int iNode, int *freqInMHz);

Reads the processor frequency MSR on the package specified by iNode, and returns the frequency in MHz in freqInMHz.

int GetTDP(int iNode, double *TDP);

Reads the package power info MSR on the package specified by iNode, and returns the TDP in watts in TDP.

int GetMaxTemperature(int iNode, int *degreeC);

Reads the temperature target MSR on the package specified by iNode, and returns the maximum temperature in degrees Celsius in degreeC.

int GetTemperature(int iNode, int *degreeC);

Reads the temperature MSR on the package specified by iNode, and returns the current temperature in degrees Celsius in degreeC.

int ReadSample();

Reads sample data from the driver for all the supported MSRs. Note that two calls to ReadSample are necessary to calculate power data, as power data is calculated using the difference between two samples.

int GetSysTime(void *pSysTime);

Returns the system time as of the last call to ReadSample. The data returned in pSysTime is structured as follows:

pSysTime[63:32] = time in seconds

pSysTime[31:0] = time in nanoseconds

int GetRDTSC(uint64_t *pTSC);

Returns in pTSC the processors time stamp counter as of the last call to ReadSample. Note that this function does not execute the rdtsc instruction directly, but instead returns the TSC from when the last sample was read.

int GetTimeInterval(double *pOffset);

Returns in pOffset the time in seconds that has elapsed between the two most recent calls to ReadSample.

int GetBaseFrequency(int iNode, double *pBaseFrequency);

Returns in pBaseFrequency the advertised processor frequency for the package specified by iNode.

int GetPowerData(int iNode, int iMSR, double *pResult, int *nResult);

Returns the data collected by the most recent call to ReadSample. The returned data is for the data on the package specified by iNode, from the MSR specified by iMSR. The data is returned in pResult, and the number of double results returned in pResult is returned in nResult. Frequency MSRs (function 0) return 1 result, which represents the frequency in megahertz. Power MSRs (function 1) return 3 results, which represent the average power in watts, cumulative energy in Joules, and cumulative energy in milliwatt-hours. Temperature MSRs (function 2) return 1 result, which represents the temperature in degrees Celsius.

int StartLog(char *szFileName);

Starts saving the data collected by ReadSample. When StopLog is called, this data will be written to the file specified by szFileName. Note that the Windows version uses wchar_t. StartLog will cause an initial call to ReadSample.

int StopLog();

Stops saving data and writes all saved data to the file specified by the call to StartLog. StopLog will cause a final call to ReadSample.