Adding Intel® Energy Checker SDK Instrumentation to Your Application-a POV-Ray* Instrumentation Tutorial

Download Article

Download Adding Intel® Energy Checker SDK Instrumentation to Your Application-a POV-Ray* Instrumentation Tutorial [PDF 1.5MB]

 

Abstract

This tutorial will show you how to add Intel® Energy Checker SDK instrumentation to your application and how to quantitatively measure energy. We used POV-Ray*, a popular open source ray-tracing application, to illustrate the benefits of using the Energy Checker SDK. We can measure the speed and the quantity of the work by running the POV-Ray instrumented with basic productivity counters. To measure how much work has been done per Joule, we ran the POV-Ray with energy efficiency counters with the help of an external power meter. Our goal is to provide developers a quantitative measurement methodology on energy efficiency of software applications. With the quantitative measurements before and after the optimization effort, developers can determine how much the optimization improves the energy efficiency.

 

1. Introduction

The energy efficiency of software has a significant impact on the battery life for mobile devices and effects the power cost of data center servers. Intel Energy Checker SDK has a small set of simple APIs (Application Programming Interface) for software instrumentation to measure the energy efficiency of applications. With the data generated by Intel Energy Checker SDK, you will understand how much useful work per Joule or per Watt has been done. To demonstrate the usage of the APIs, this tutorial shows how to instrument POV-Ray with Intel Energy Checker SDK.

 

2. POV-Ray Setup

Intel Energy Checker SDK supports Windows*, Linux*, Solaris 10* and MacOS X* OSs. This tutorial assumes you are running a POV-Ray setup on a desktop or laptop with Windows 7. Basic performance measurements require only the software listed below, but an external power meter is needed to measure energy efficiency. We used a YOKOGAWA WT210 power meter with a COM to USB converter cable.

The setup requires the following software:

2.1. Install POV-Ray

After downloading and installing the POV-Ray setup program, “POV-Ray for Windows V3.7 RC5” appears in the Windows menu Start->All Programs. Generally, the execution binary pvengine.exe is installed under C:\Program Files\POV-Ray\v3.7 RC5\bin. Later in this tutorial, you will replace this binary with one created from the POV-Ray source code with added Intel Energy Checker instrumentation.

2.2. Build and Compile POV-Ray

After downloading the POV-Ray source code, open the project file povwin-src-3.7.RC3\povwin-src-3.7-RC3\windows\vs9\povray.sln with Visual Studio 2008. Figure 1 shows the projects in the ‘povray’ solution.


Figure 1: Solution Explorer view of POV-Ray in Visual Studio 2008

Next, either set the $BOOST_PATH environment variable to the boost 1.37 installation path, or replace all $BOOST_PATH macros by the boost 1.37 installation path. Figure 2 shows the GUI property page where you need to change the $BOOST_PATH by installing the path in the additional include directories area. After doing this, make sure the programs are compile-able.


Figure 2: GUI Property Page to change $BOOST_PATH

2.3 Build POV-Ray with Intel Energy Checker SDK

A folder named iecsdk appears after downloading and unzipping the Intel Energy Checker SDK. It contains six subfolders: bin, build, doc, license, src, and utils. The simple core APIs are declared and defined in the files productivity_link.h and productivity_link.c under the folder iecsdk\src\core_api\. Through the core API calls, a software application is able to create/open/read a folder with a unique name under c:\productivity_link. These folders record the current application productivity data and can be opened/read by other applications for monitoring/logging etc.

Step 1: Open the folder iecsdk\src\core_api\. Add both the productivity_link.c and productivity_link.h files into the GUI project in the POV-Ray solution.

Step 2: Go to GUI project property->C/C++/Preprocessor and add the preprocessor definitions to the GUI project, as shown in Figure 3. The Intel Energy Checker SDK user guide has details on all the preprocessor definitions, but here are a few of the basic preprocessor definition options:.

__PL_EXTRA_INPUT_CHECKS__ __PL_WINDOWS__ __PL_GENERATE_INI__ __PL_GENERATE_INI_VERSION_TAGGING__ __PL_GENERATE_INI_BUILD_TAGGING__ __PL_GENERATE_INI_DATE_AND_TIME_TAGGING__ __PL_BLOCKING_COUNTER_FILE_LOCK__


Figure 3: GUI project preprocessor setting

Step 3: Change the Properties->C/C++->Precompiled Header->Create/Use Precompiled Header to “Not Using Precompiled Headers”, as shown in Figure 4.


Figure 4: GUI project precompiled header setting

2.4 Build POV-Ray with Instrumentation

To record the POV-Ray in “idle,” “not running,” and “rendering” states, use the Intel Energy Checker SDK APIs for basic instrumentation with a software phase counter.

Step 1: Intel Energy Checker SDK will create a productivity link folder under the directory for the instrumentation. Create a directory as c:\productivity_link for this folder.

Step 2: In the main file for the POV-Ray engine, pvengine.cpp, include productivity_link.h to use the SDK APIs.

#include "productivity_link.h"

Step 3: At the beginning of pvengine.cpp, define the counters to be instrumented, and the productivity link to be created by Intel Energy Checker SDK. This is illustrated in Sample Code 1 and includes the definitions on the instrumented application name, the number of counters, the counter names, the counter value definition, and the variable for the counter and the variable for the productivity link.

#define APPLICATION_NAME "PovRayInstrument"
// Maximum number of the instrumented counters.
#define MAX_COUNTERS 1
// Counter name that will be exposed in productivity link folder.
#define COUNTER_NAMES {
	"Software Phase", 
}
// Software phase counter definition.
#define POV_RAY_NOT_RUNNING 0 //POV-Ray is not running.
#define POV_RAY_IDLE 1 //POV-Ray is in idle state.
#define POV_RAY_RENDERING 2 //POV-Ray is rending pictures.

//Softare phase counter variable initialization.
ULONGLONG export_sw_phase = POV_RAY_IDLE;
enum {
	PL_SW_PHASE = 0,
};
// Counter name list that will be inputed to IEC APIs. 
const char *counters[MAX_COUNTERS] = COUNTER_NAMES;
// PL created for the counters
int pl_w = PL_INVALID_DESCRIPTOR;
// PL return value from pl API calls
int pl_ret = PL_FAILURE;

Sample Code 1: Define the global? micros and variables **

Step 4: At the beginning of pvengine.cpp::WinMain function, use pl_open to create a productivity link folder with an automatically created GUID under c:\productivity_link, as shown in Figure 5. The folder includes a pl_config.ini and the files for all the counters (each counter is associated with a file). Pl_open returns the productivity link id. Then use the productivity link id to write the counters to the folder and the associated counter file. Write the software phase with POV_RAY_IDLE state at the beginning of POV-Ray.

int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {
  ……
  
  uuid_t pl_uuid;
  int ret = PL_FAILURE;

  //-----------------------------------------------------------------------
  // Create/Open the PL config file (PL) - for all the defined counters 
  //-----------------------------------------------------------------------
  pl_w = pl_open(APPLICATION_NAME, MAX_COUNTERS, counters, &pl_uuid); 
  assert(pl_w != PL_INVALID_DESCRIPTOR);

  //-----------------------------------------------------------------------
  // Write the counter export_sw_phase 's value to PL folder 
  //-----------------------------------------------------------------------
  export_sw_phase = POV_RAY_IDLE;
  pl_ret = pl_write(pl_w, &export_sw_phase, PL_SW_PHASE); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 2: Use pl_open call to create a productivity link and use pl_write call to record software phase to the productivity link **


Figure 5: The productivity link folder created by the instrumented POV-Ray

Step 5: Build and run the code. Figure 5 shows the pl_config.ini file under the productivity link folder: C:\productivity_link\PovRayInstrument_6c9cb070-a0b0-4f4f-8155-d42d64d2de28. Figure 6 shows the content of the pl_config.ini file.

PovRayInstrument
6c9cb070-a0b0-4f4f-8155-d42d64d2de28
C:productivity_linkPovRayInstrument_6c9cb070-a0b0-4f4f-8155-d42d64d2de28
1
C:productivity_linkPovRayInstrument_6c9cb070-a0b0-4f4f-8155-d42d64d2de28Software Phase
2010.12.15.(W)
_DEBUG
__PL_EXTRA_INPUT_CHECKS__
__PL_WINDOWS__
__PL_GENERATE_INI__
__PL_GENERATE_INI_VERSION_TAGGING__
__PL_GENERATE_INI_BUILD_TAGGING__
__PL_GENERATE_INI_DATE_AND_TIME_TAGGING__
__PL_BLOCKING_COUNTER_FILE_LOCK__
PL created on Mon Jun 11 13:39:52 2012

Figure 6: Content of an example pl_config.ini

The value in the Software Phase file is the current value of export_sw_phase, which is 1 (POV_RAY_IDLE).

Possible issue: You may encounter an issue at this point if you use pl_open in the instrumentation and you produce the productivity link folder that begins with a letter, for example:

C:\productivity_link\P_6c9cb070-a0b0-4f4f-8155-d42d64d2de28\

If you get the counter file name “S” instead of “Software Phase”, you are experiencing a bug with Visual Studio 2008 wide character conversion. The problem is easily fixed in the productivity_link.c by replacing the call to wcstombs_s with the call to_tcsnccpy_s in lines 2919, 2952, 3056, 11256, 11536, 11544. The change is shown in Sample Code 3.

	//-------------------------------------------------------------------
	// 002: write uuid.
	//-------------------------------------------------------------------
	ZeroMemory(
		pl_ini_buffer, 
		sizeof(pl_ini_buffer)
	);
	
	_tcsnccpy_s(
		pl_ini_buffer, 
		sizeof(pl_ini_buffer), 
		p, 
		_TRUNCATE
	); // Ln 2919

      ……
Ln 2952  replace wcstombs_s by _tcsnccpy_s
Ln 3056  replace wcstombs_s by _tcsnccpy_s
Ln 11256 replace wcstombs_s by _tcsnccpy_s
Ln 11536 replace wcstombs_s by _tcsnccpy_s
Ln 11544 replace wcstombs_s by _tcsnccpy_s

Sample Code 3: Fixing a wide character conversion issue in productivity_link.c **

Step 6: To intitate instrument rendering, use pl_write to write the software phase counter as POV_RAY_RENDERING at the end of the function start_rendering in pvengine.cpp, as shown in Sample Code 4.

  rendering = true ;
  //-----------------------------------------------------------------------
  // Write the counter export_sw_phase 's value to PL folder 
  //-----------------------------------------------------------------------
  export_sw_phase = POV_RAY_RENDERING;
  pl_ret = pl_write(pl_w, &export_sw_phase, PL_SW_PHASE); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 4: Use pl_write call to record the software phase in the pvengine.cpp::start_rendering function. **

Step 7: After the rendering stops, in the function render_stopped in pvengine.cpp, use pl_write to write the software phase counter as POV_RAY_IDLE, as shown in Sample Code 5.

  rendering = false ;
  //-----------------------------------------------------------------------
  // Write the counter export_sw_phase 's value to PL folder 
  //-----------------------------------------------------------------------
  export_sw_phase = POV_RAY_IDLE;
  pl_ret = pl_write(pl_w, &export_sw_phase, PL_SW_PHASE); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 5: Use the pl_write call to record the software phase counter in the pvengine.cpp::renderstopped **

Step 8: At the end of the program, before the POV-Ray engine exits, write the software phase as POV_RAY_NOT_RUNNING and use pl_close to close the productivity link, as shown in Sample Code 6.

    if(pl_w != PL_INVALID_DESCRIPTOR) {
	  pl_ret = PL_FAILURE;
        //-----------------------------------------------------------------
        // Write the counter export_sw_phase 's value to PL folder 
        //-----------------------------------------------------------------
	  export_sw_phase = POV_RAY_NOT_RUNNING;
	  pl_ret = pl_write(pl_w, &export_sw_phase, PL_SW_PHASE); 
	  assert(pl_ret == PL_SUCCESS);
        //-----------------------------------------------------------------
        // Close PL  
        //-----------------------------------------------------------------
	  pl_ret = pl_close(pl_w); 
	  assert(pl_ret == PL_SUCCESS);
	}

Sample Code 6: Use pl_close call to close the productivity link before POV-Ray engine exits **

Users are able to monitor the software phase of the POV-Ray engine with the instrumentation. To further understand the application’s performance and energy usage, you can enhance the instrumentation with productivity and energy efficiency counters.

 

3. POV-Ray Instrumentation for Productivity

In this section, you’ll instrument the POV-Ray with performance counters to obtain simple productivity metrics. For a POV-Ray rendered image, it is important to know the running total of rendered pixels and the current rendered pixels per second. The total shows how much useful work has been done, and the rendered pixels per second shows how fast it was completed. Both productivity metrics are measured by the counters with instrumentation.

Step 1: Define two more counters in pvengine.cpp, as shown in Sample Code 7.

#define APPLICATION_NAME "PovRayInstrument"
// Maximum number of the instrumented counters.
#define MAX_COUNTERS 3
// Counter name that will be exposed in productivity link folder.
#define COUNTER_NAMES {
	"Software Phase", 
	"Number of pixels rendered", 
	"Pixels render per second", 
}
// Software phase counter definition.
#define POV_RAY_NOT_RUNNING 0 //POV-Ray is not running.
#define POV_RAY_IDLE 1 //POV-Ray is in idle state.
#define POV_RAY_RENDERING 2 //POV-Ray is rending pictures.

//Softare phase counter variable initialization.
ULONGLONG export_sw_phase = POV_RAY_IDLE;
ULONGLONG export_pixels_render = 0;
ULONGLONG export_pixels_render_per_second = 0;
enum {
	PL_SW_PHASE = 0,
	PL_PIXELS_RENDER,
	PL_PIXELS_RENDER_PER_SECOND,
};
// Counter name list that will be inputed to IEC APIs. 
const char *counters[MAX_COUNTERS] = COUNTER_NAMES;
// PL created for the counters
int pl_w = PL_INVALID_DESCRIPTOR;
// PL return value from pl API calls
int pl_ret = PL_FAILURE;

Sample Code 7: Define global macros and variables for performance counters **

Step 2: Sample Code 8 illustrates how to use pl_write to initialize the two counters in the productivity link created by pl_open in the pvengine.cpp::WinMain function.

  //--------------Right after the pl_open call in WinMain ----------------
  //-----------------------------------------------------------------------
  // Write the counters initialization values to the associated PL file 
  //-----------------------------------------------------------------------
  export_pixels_render = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render, PL_PIXELS_RENDER); 
  assert(pl_ret == PL_SUCCESS);

  export_pixels_render_per_second = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render_per_second, 
  PL_PIXELS_RENDER_PER_SECOND); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 8: Initialize all the performance counters when program starts**

Step 3: At the start of the rendering process, in the call of the pvengine.cpp::start_rendering function, add the initialization values of the counters for a POV-Ray file, as illustrated in Sample Code 9.

  //--------------In the pvengine.cpp::start_rendering function call ------
  Rendering = true;
  //-----------------------------------------------------------------------
  // Write the counters initialization values for a POV-Ray file to the 
  // associated PL file. 
  //-----------------------------------------------------------------------
  export_pixels_render = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render, PL_PIXELS_RENDER); 
  assert(pl_ret == PL_SUCCESS);

  export_pixels_render_per_second = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render_per_second, 
  PL_PIXELS_RENDER_PER_SECOND); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 9: Initialize the performance counters which? starts rendering a POV_Ray file. ** This is not clear, please re-word.

Step 4: Next add two basic productivity counters-pixels_render and pixels_render_per_second-in the instrumentation, which requires to call pl_write to record them in the productivity link. Both counters are calculated and recorded when a function pvengine.cpp::PrintRenderTimes is called for the rendering of each image. Sample Code 10 shows how to record the two counters to the productivity link in the function pvengine.cpp::PrintRenderTimes.

  //------In the pvengine.cpp::PrintRenderTimes function call -----
  ClockTimeTotal = ClockTimeEnd - ClockTimeStart - STT ;
  //-----------------------------------------------------------------------
  // Write the counters values for a POV-Ray file to the associated PL.
  //-----------------------------------------------------------------------
  int previous_pixels_render  = export_pixels_render; 

  export_pixels_render = PixelsRendered;
  pl_ret = pl_write(pl_w, &export_pixels_render, PL_PIXELS_RENDER); 
  assert(pl_ret == PL_SUCCESS);

  export_pixels_render_per_second = 
	  (int)((double)(PixelsRendered - previous_pixels_render)   
                    /(double)(ClockTimeTotal / CLOCKS_PER_SEC));
  pl_ret = pl_write(pl_w, &export_pixels_render_per_second,                 
                    PL_PIXELS_RENDER_PER_SECOND); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 10: Calculate the performance counters and record them into the productivity link during the rendering **

Step 5: After the rendering stops at pvengine.cpp::render_stopped, use pl_write to adjust the export_pixels_render_per_second counter to 0.

At this point, the instrumentation for the simple productivity metrics is complete. With the companion application, pl_gui_monitor (refer to Section 5.1 for how to use pl_gui_monitor), we can monitor the counters online as in Figure 7. On the left, the counters are being monitored by pl_gui_monitor and, on the right, is POV-Ray rendering an image.


Figure 7: Running instrumented POV-Ray and monitoring the productivity counters with pl_gui_monitor

These steps show how to instrument POV-Ray with basic productivity counters. The instrumentation and the companion tool, pl_gui_monitor, monitor the value changes of the counters. In the example, you can see how many pixels have been rendered and how fast the work has been done by monitoring the counters.

 

4. POV-Ray Instrumentation for Energy Efficiency

Intel Energy Checker can collect power/energy data from a hardware power meter. In this section, you will instrument the POV-Ray with energy efficiency counters in order to determine the number of rendered pixels per Joule.

4.1. Main Idea

Figure 8 illustrates the plan to set up the instrumentation to monitor energy efficiency. First, connect an external power meter via COM-to-USB cable to the target machine that runs POV-Ray. It measures the energy consumption and passes the data through the cable to a COM port of the target machine. The Intel Energy Checker provides an executable, named ESRV, to communicate with several kinds of external power meters through a COM port. ESRV also produces the productivity link in the folder c:\productivity_link with all the values from the meter. The instrumented POV-Ray reads the energy consumption from the productivity link and calculates and writes the energy efficiency counters to its own productivity link.


Figure 8: Software communication diagram and hardware connection for the POV-Ray instrumentation for energy efficiency

4.2. Run ESRV

The Intel Energy Checker SDK package includes the binaries ESRV under the bin folder. We ran the ESRV with a YOKOGAWA WT210 power meter.

Step 1: Go to the folder iecsdk\bin\energy_server\windows\X64 or X86 and find the ESRV binary.

Step 2: Configure the WT210 with the setup that can measure power and energy. Refer to the WT210 user manual.

Step 3: Connect the target machine and the external power meter as in Figure 7. If the target machine is a laptop, remove the battery or make sure it is fully charged. The power/energy measured by the external power meter includes the battery and any recharging will alter the results. After the COM-USB converter cable is inserted into the target machine, a COM port is added in Device Manager->Ports (COM & LPT). Record the COM port number. In our case it is COM1.

Step 4: Under an elevated cmd window, as an Administrator, run the following command:

esrv --start --device y210 --device_options "items=w1" --interface_options "COM=1 baud=9600 parity=n data=8 stop=1 xon=n dtr=n rts=y"

Note that COM port number in the command should be the same as the port for the power meter. Figure 8 shows the window that appears, and the ESRV created a new PL with the automatically created GUID.


Figure 8: Screenshot of a running ESRV with a YOKOGAWA WT210 power meter

If you browse to the folder c:\productivity_link, a new folder is created: esrv_7997c441-fcba-42b4-b80e-2677f3aa3b6e. It includes a pl_config.ini file with the format shown in Figure 9. The first counter is the energy consumption in Joules and the second counter indicates the first counter has decimal numbers. After you open the file for the second counter, it is always two and means the first counter “energy” has two decimal numbers. When you convert the first counter to Joules, you need to divide the value by 100.

esrv
7997c441-fcba-42b4-b80e-2677f3aa3b6e
C:productivity_linkesrv_7997c441-fcba-42b4-b80e-2677f3aa3b6e
63
C:productivity_linkesrv_7997c441-fcba-42b4-b80e-2677f3aa3b6e[CHANNEL1] - Energy (Joule)
C:productivity_linkesrv_7997c441-fcba-42b4-b80e-2677f3aa3b6e[CHANNEL1] - Energy (Joule).decimals
……

Figure 9: Content of the pl_config.ini created by ESRV with a YOKOGAWA WT210 power meter

4.3. Instrument POV-Ray

Next, you will instrument the POV-Ray for the energy efficiency counters with the productivity link created by ESRV.

Step 1: Define three more counters in pvengine.cpp, as shown in Sample Code 10. The first is the raw energy reading in Joules. This comes from the productivity link created by ESRV with external power meter device. The other two counters show the energy consumption for rendering an image and the average pixels rendered per Joule.

#define APPLICATION_NAME "PovRayInstrument"
// Maximum number of the instrumented counters.
#define MAX_COUNTERS 6
// Counter name that will be exposed in productivity link folder.
#define COUNTER_NAMES {
	"Software Phase", 
	"Number of pixels rendered", 
	"Pixels rendered per second", 
	"Raw energy reading in Joules", 
	"Energy for render in Joules", 
	"Pixels rendered per Joules", 
}
// Software phase counter definition.
#define POV_RAY_NOT_RUNNING 0 //POV-Ray is not running.
#define POV_RAY_IDLE 1 //POV-Ray is in idle state.
#define POV_RAY_RENDERING 2 //POV-Ray is rending pictures.

//Softare phase counter variable initialization.
ULONGLONG export_sw_phase = POV_RAY_IDLE;
ULONGLONG export_pixels_render = 0;
ULONGLONG export_pixels_render_per_second = 0;
ULONGLONG export_energy_reading = 0;
ULONGLONG export_energy_for_render = 0;
ULONGLONG export_pixels_render_per_joule = 0;

enum {
	PL_SW_PHASE = 0,
	PL_PIXELS_RENDER,
	PL_PIXELS_RENDER_PER_SECOND,
	PL_ENERGY_READING_IN_J,
	PL_ENERGY_FOR_RENDER_IN_J,
	PL_PIXELS_RENDER_PER_J,
};
enum {
	PL_ENERGY = 0,
	PL_ENERGY_DECIMAL,
};
// Counter name list that will be inputed to IEC APIs. 
const char *counters[MAX_COUNTERS] = COUNTER_NAMES;
// PL created for the counters
int pl_w = PL_INVALID_DESCRIPTOR;
// PL return value from pl API calls
int pl_ret = PL_FAILURE;
// PL created for the energy from the PL created by ESRV with power meter
int pl_r = PL_INVALID_DESCRIPTOR;

Sample Code 10: Define global macros and variables for energy efficiency counters **

Step 2: Create a user-prompt window and select the productivity link (pl_config.ini file) created by ESRV with an external power meter device. Use pl_attach to connect the counters in the productivity link. The pl_attach returns the productivity link id. Later, you use the id with pl_read to read the most recent values of the counters. Refer to Sample Code 11.

  //--------------Right after the pl_open and pl_write calls for previous 
  // -------------productivity counters in WinMain ----------------
  //-----------------------------------------------------------------------
  // Instrumentation for attaching energy PL for the energy efficiency counters 
  //-----------------------------------------------------------------------

  OPENFILENAME ofn;
  char file_energy[MAX_PATH];
  ZeroMemory(file_energy, sizeof(file_energy));
  ZeroMemory(&ofn, sizeof(ofn));

  //-----------------------------------------------------------------------
  // Browse for the PL config file (PL) created by esrv with power meter  
  // device -energy counter source
  //-----------------------------------------------------------------------
  ofn.lStructSize = sizeof(ofn);
  ofn.hwndOwner = NULL;
  ofn.lpstrFile = file_energy;
  ofn.nMaxFile = sizeof(file_energy);
  ofn.lpstrFilter = _T("PL Configuration File�*.INI�");
  ofn.nFilterIndex = 1;
  ofn.lpstrFileTitle = NULL;
  ofn.nMaxFileTitle = 0;
  ofn.lpstrInitialDir = NULL;
  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

  b_ret = GetOpenFileName(&ofn);
  assert(b_ret);

  //-----------------------------------------------------------------------
  // Attach to the energy counters (PL)
  //-----------------------------------------------------------------------
  pl_r = pl_attach(file_energy); 
  assert(pl_r != PL_INVALID_DESCRIPTOR);

  // Read the energy value from the ESRV device producitivity link
  pl_ret = pl_read(pl_r, &export_energy_reading, PL_ENERGY); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 11: Create a user-prompt window for selecting the productivity link created by ESRV with an external power meter**

Step 3: Use pl_write to initialize the two counters in the productivity link created by pl_open in the pvengine.cpp::WinMain function. See Sample Code 12.

  //--------------Right after the pl_read call for 
  // -------------the energy reading in WinMain ----------------
  //-----------------------------------------------------------------------

  // Write the energy value to the current PL
  // Convert to Joules as the energy counter has two decimals. 
  export_energy_reading /= 100;  
  pl_ret = pl_write(pl_w, &export_energy_reading, PL_ENERGY_READING_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Initialize the energy for rendering counter
  export_energy_for_render = 0;
  pl_ret = pl_write(pl_w, &export_energy_for_render,
                    PL_ENERGY_FOR_RENDER_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Initialize the pixels rendereed per joule counter
  export_pixels_render_per_joule = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render_per_joule, 
                    PL_PIXELS_RENDER_PER_J); 
  assert(pl_ret == PL_SUCCESS);

Sample code 12: initialize the energy efficiency counters when the program starts**

Step 4: Add the initialization values of the counters for a POV-Ray image rendering file when the rendering process begins, in the call of the pvengine.cpp::start_rendering function. Sample Code 13 illustrates this.

  //--------------In the pvengine.cpp::start_rendering function call ------
  Rendering = true;

  // Read the energy value from the ESRV device producitivity link
  pl_ret = pl_read(pl_r, &export_energy_reading, PL_ENERGY); 
  assert(pl_ret == PL_SUCCESS);

  // Write the energy value to the current PL
  // Convert to mJoules as the energy counter has two decimals. 
  export_energy_reading /= 100; 
  pl_ret = pl_write(pl_w, &export_energy_reading, PL_ENERGY_READING_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Initialize the energy for rendering counter
  export_energy_for_render = 0;
  pl_ret = pl_write(pl_w, &export_energy_for_render, 
                    PL_ENERGY_FOR_RENDER_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Initialize the pixels rendereed per joule counter
  export_pixels_render_per_joule = 0;
  pl_ret = pl_write(pl_w, &export_pixels_render_per_joule, 
                    PL_PIXELS_RENDER_PER_J); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 13: Initialize the energy efficiency counters at the start of rendering an image**

Step 5: After the render stops in the the call of pvengine.cpp:: render_stopped, use pl_write to adjust the export_pixels_render_per_second counter to 0.

Step 6: A function PrintRenderTimes is called to produce rendering statistics. Write the statistics from the two counters into the productivity link, as shown in Sample Code 14.

  //------In the pvengine.cpp::PrintRenderTimes function call -----
  ClockTimeTotal = ClockTimeEnd - ClockTimeStart - STT ;
  ……
  //
  // After write export_pixels_render_per_second, read energy counter and 
  // compute the energy efficiency counters.
  //
  ULONGLONG previous_energy_reading = export_energy_reading;

  // Read the energy value from the ESRV device producitivity link
  pl_ret = pl_read(pl_r, &export_energy_reading, PL_ENERGY); 
  assert(pl_ret == PL_SUCCESS);

  // Write the energy value to the current PL
  // Convert to Joules as the energy counter has two decimals. 
  export_energy_reading /= 100; 
  pl_ret = pl_write(pl_w, &export_energy_reading, PL_ENERGY_READING_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Calculate and write the energy for rendering counter
  export_energy_for_render = export_energy_reading – 
                             previous_energy_reading;
  pl_ret = pl_write(pl_w, &export_energy_for_render, 
                    PL_ENERGY_FOR_RENDER_IN_J); 
  assert(pl_ret == PL_SUCCESS);

  // Calculate and write the pixels rendereed per joule counter
  export_pixels_render_per_joule = 
            (int)((double) (PixelsRendered - previous_pixels_render)
                 /(double)export_energy_for_render);
  pl_ret = pl_write(pl_w, &export_pixels_render_per_joule, 
                    PL_PIXELS_RENDER_PER_J); 
  assert(pl_ret == PL_SUCCESS);

Sample Code 14: Record the energy efficiency counters during rendering**

Now the instrumentation for the energy-efficient productivity counters is done. When using the instrumented POV-Ray with ESRV, the energy efficiency counters are measured and passed to the productivity link. By monitoring and logging the counter data, you have quantitative knowledge on how much energy has been used for useful work. If you optimize the application in terms of performance or power, you should compare the values of the counters before and after the optimization. By comparing the results, you can determine whether the optimization improved energy efficiency or not. During the comparison, make sure the battery of the device is not in charging mode.

The steps on how to run the POV-Ray with ESRV will be shown in Section 4.4. Further, with the help of companion tools like pl_gui_monitor and pl_csv_logger, you can monitor the counter value changes via graphical UI and log the online data values to a csv file with timestamps. Section 5 will show how to use these tools with the instrumented POV-Ray.

4.4. Run the Instrumented POV-Ray with ESRV

While ESRV is running with a GUID, open a CMD window and run the instrumented POV-Ray pvengine.exe.

At first, the instrumented POV-Ray opens a window, like Figure 5, for the user to select the ESRV productivity link to attach to for the energy reading. Be sure to select the one with the GUID that is running the ESRV.

Run the POV-Ray as normal. The POV-Ray creates a productivity link folder with a new GUID with the six counters (Figure 10). The three energy efficiency counters are “Raw energy reading in Joules,” “Energy for render in Joules,” and “Pixels rendered per Joule”.


Figure 10: Screenshot of the productivity folder created by the instrumented POV-Ray for energy efficiency


5. Usage of pl_gui_monitor and pl_csv_logger with the Instrumented POV-Ray

5.1. pl_gui_monitor

Intel Energy Checker SDK includes a companion application to the ESRV. With the pl_gui_monitor, we view metrics in a graphical window while running the instrumented POV-Ray and ESRV.

Step 1: Go to iecsdk\bin\companion_applications\pl_gui_monitor\windows\X64 or X86 and find the pl_gui_monitor.exe binary.

Step 2: A window opens. Select the pl_config.ini to be monitored. Select the pl_config.ini created by the instrumented POV-Ray.

Step 3: Figure 11 shows a graphical window on the left displaying the six counters. When you click “run to render an image,” the pl_gui_monitor window will update the counter values.


Figure 11: Screenshot of pl_gui_monitor monitoring the counters measured by the instrumented POV-Ray

5.2. pl_csv_logger

Step 1: Go to iecsdk\build\windows\iecsdk\pl_csv_logger and find the project file. Build the pl_csv_logger.exe binary for x86 or X64 platform. The binary is created under the folder iecsdk\build\windows\iecsdk\debug or release or x64.

Step 2: While running the instrumented POV-Ray and ESRV, run pl_csv_logger with the following command. Be sure that the productivity link in the command matches the one created by the instrumented POV-Ray.

pl_csv_logger "C:\productivity_link\PovRayInstrument_e03c5ac2-b9f0-4f91-8828-2360d776b867\pl_config.ini" --output "c:\productivity_link\POVRay_test.csv"


Figure 12: Screenshot of pl_csv_logger running

Step 3: Use POV-Ray as normal. The pl_csv_logger records the counters sampled in a second frequency. Run Ctrl+C to stop pl_csv_logger. The specified csv file is created.

Step 4: Open the csv file, where the samples are recorded. Figure 13 shows a plot for the pixels rendered per Joule as POV-Ray renders an image. The pixels rendered per Joule vary during the rendering of an image.


Figure 13: Plot the pixels rendered per Joule from the csv file created by pl_csv_logger


6. Conclusion

This tutorial has shown you how to instrument POV-Ray with Intel Energy Checker SDK in order to measure productivity and energy efficiency. We have also illustrated how to use the companion tools for monitoring and logging the instrumented data. With the Intel Energy Checker instrumentation added to your application and a hardware power meter, you can measure how much useful work is done per Joule or per Watt.

 

7. References

Intel® Energy Checker SDK: /en-us/articles/intel-energy-checker-sdk

Ultrabook™ and the Intel® Energy Checker SDK: /en-us/articles/ultrabook-and-the-intel-energy-checker-sdk

Build POV-Ray* with Intel® C++ Compiler: /en-us/articles/compilepovray

Build POV-Ray* for Windows* Source: http://www.povray.org/beta/source/povwin-src-readme.html


About the Author

Sushu Zhang is a software engineer in Intel Corporation's Software and Services Group. She is working on ISV scale enabling for Intel-based platforms with Android* and Windows OSs. She developed the Intel® Power Monitoring Tool for Android devices. Most recently, Sushu has been involved with several energy-efficiency projects at Intel. Prior to joining Intel, Sushu worked at Microsoft on Windows energy efficiency. Sushu earned a Ph.D in Computer Science at the Arizona State University. Her research area was system level power and thermal management.




*Other names and brands may be claimed as the property of others.

**The sample source code in the article is released under the Intel Sample Source Code License Agreement and POV-Ray License v3.5.

Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.