Using the Intel Power Gadget API on Mac OS X

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.

AttachmentSize
Downloadapplication/zip intel-power-gadget-api.zip3.09 MB
For more complete information about compiler optimizations, see our Optimization Notice.

Comments

Hi Patrick,

Hi Patrick,

MSRs are read with ring 0 privilege from a kext.

The Frequency scale is working in the Intel Power Gadget but the "Power" scale (up to 84 Watts) is not working properly. All we see is a small ripple (on the null line) but that's about it. Same thing for the IGPU line.

Thank you.

Pike



I installed the latest

I installed the latest developer seed of 10.9.3 (Build 13D61) on my testbed, with a Intel Haswell i5-4670K, but other people reported the same problem with OS X 10.9.2 and their i7-4770K.

I'm aware of HSD111: MSR_PP1_ENERGY_STATUS MSR (641H) bits [31:0] reports incorrect energy data, but I can't seem to locate one for MSR_PP0_ENERGY_STATUS. By the way. There appears to be a workaround for this erratum, but what is it?

@Patrick,

Do you have any kind of issue with respect in replying to me here in public, then feel free to contact me per e-mail.

Thank you!



The Intel Power Gadget fails

The Intel Power Gadget fails to show the estimated energy consumption and this is probably the result of some MSR's being zero (see list below) but can something be done to resolve this issue or is it a hardware (UEFI BIOS) problem?

MSR_CORE_THREAD_COUNT......(0x35)  : 0x40004
MSR_PLATFORM_INFO..........(0xCE)  : 0x80838F3012200
MSR_PMG_CST_CONFIG_CONTROL.(0xE2)  : 0x1E000005
MSR_PMG_IO_CAPTURE_BASE....(0xE4)  : 0x21814
IA32_MPERF.................(0xE7)  : 0xE10D2E66D
IA32_APERF.................(0xE8)  : 0xC124968B3
MSR_FLEX_RATIO.............(0x194) : 0xE0000
MSR_IA32_PERF_STATUS.......(0x198) : 0x203B00002300
MSR_IA32_PERF_CONTROL......(0x199) : 0x2600
IA32_CLOCK_MODULATION......(0x19A) : 0x0
IA32_THERM_STATUS..........(0x19C) : 0x88440000
IA32_MISC_ENABLES..........(0x1A0) : 0x850089
MSR_MISC_PWR_MGMT..........(0x1AA) : 0x1
MSR_TURBO_RATIO_LIMIT......(0x1AD) : 0x23242526
IA32_ENERGY_PERF_BIAS......(0x1B0) : 0xF
MSR_POWER_CTL..............(0x1FC) : 0x4005F
MSR_RAPL_POWER_UNIT........(0x606) : 0xA0E03
MSR_PKG_POWER_LIMIT........(0x610) : 0xFFD00000EA82
MSR_PKG_ENERGY_STATUS......(0x611) : 0xEA267
MSR_PKG_POWER_INFO.........(0x614) : 0x2A0
MSR_PP0_CURRENT_CONFIG.....(0x601) : 0x10141400001F40
MSR_PP0_POWER_LIMIT........(0x638) : 0x0
MSR_PP0_ENERGY_STATUS......(0x639) : 0x0
MSR_PP0_POLICY.............(0x63a) : 0x0
MSR_PP1_POWER_LIMIT........(0x640) : 0xFFD0
MSR_PP1_ENERGY_STATUS......(0x641) : 0x0
MSR_PP1_POLICY.............(0x642) : 0x18
MSR_CONFIG_TDP_NOMINAL.....(0x648) : 0x22
MSR_CONFIG_TDP_LEVEL1......(0x649) : 0x0
MSR_CONFIG_TDP_LEVEL2......(0x64a) : 0x0
MSR_CONFIG_TDP_CONTROL.....(0x64b) : 0x80000000
MSR_TURBO_ACTIVATION_RATIO.(0x64c) : 0x0
MSR_PKGC3_IRTL.............(0x60a) : 0x8842
MSR_PKGC6_IRTL.............(0x60b) : 0x886A

MSR_PKGC7_IRTL.............(0x60c) : 0x8891

MSR_PKG_C2_RESIDENCY.......(0x60d) : 0x247647320E
MSR_PKG_C3_RESIDENCY.......(0x3f8) : 0x0
MSR_PKG_C6_RESIDENCY.......(0x3f9) : 0x0
MSR_PKG_C7_RESIDENCY.......(0x3fa) : 0x0