Using Intel Performance Counter Monitor on Mac OS X

Table of Contents

What I’m doing

I needed to profile a C++ method for a graduate course I’m taking. More specifically, I wanted to be able to see memory access patterns and how the hit ratios for cache memory were affected by different coding strategies.

The alternative I chose was Intel’s Performance Counter Monitor (PCM), documented and freely available for download at Intel’s website.

Although not difficult, using it wasn’t as straightforward as I would have liked, so here’s a straight to the point setup tutorial for Mac OS X.

What you’ll need

  1. Download Intel PCM here and extract it wherever you like to keep your libraries and packages. I’ll refer to this directory as _$(PCMROOT).

  2. XCode (I’m using version 5, but it should work just as well with previous versions - PCM requires at least XCode 4.2; gcc and make should be available as well).

  3. A C++ application you can’t wait to profile!

Step 1: Install PCM

To use PCM, its drivers must be built and properly installed. We’re going to opt for the Automatic install, since we don’t need to place the generated files anywhere specific. For this, administrator privilege, (sudo), will be needed.

Load up Terminal and cd your way into _$(PCMROOT). Now it’s basically the specific instructions that ship with PCM, namely:

$ cd MacMSRDriver
$ make install

This is what’s happening:

kextload.sh will load the driver, libPcmMsr.dylib will be placed in /usr/lib and the header files MSRAccessor.h and MSRKernel.h will be copied to /usr/include.

Then, assuming everything worked out ok:

$ cd ..
$ make

This builds the utility applications and the object files and should give you the executable. To test it, for example:

$ ./pcm.x 1

If this works, Intel PCM is properly installed.

Step 2: Using PCM’s CPU Counters in your code

For me, this was the tricky part. Figuring out exactly which files to link against was basically trial and error, hence this post.

In your .cpp file, you just need to include the proper header. To do this, add the _$(PCMROOT) to the User Header Search Paths property under your project’s Build Settings on XCode. With this in place, you can simply add to your program file:

#include <cpucounters.h>

PCM methods are not encapsulated in any namespace, so you can just go ahead and use it like the example below:

PCM *m = PCM::getInstance();
m->program (PCM::DEFAULT_EVENTS, NULL);

if (m->program() != PCM::Success) return -1;

SystemCounterState before_sstate = getSystemCounterState();
// method call to be profiled goes here!
SystemCounterState after_sstate = getSystemCounterState();

std::cout << "Instructions per Clock: " << getIPC(before, after) <<
    "\nL3 cache hit ratio: " << getL3CacheHitRatio(before, after) <<
    "\nL2 cache hit ratio: " << getL2CacheHitRatio(before, after) <<
    "\nWasted cycles caused by L3 misses: " << 
    getCyclesLostDueL3CacheMisses(before, after) <<
    "\nBytes read from DRAM: " << getBytesReadFromMC(before, after)) <<
    std::endl;

m->cleanup();

Building your program now will result in linker errors. There are a few files that your application has to link against:

  • libPcmMsr.dylib
  • cpucounters.o
  • client_bw.o
  • pci.o
  • msr.o

libPcmMsr.dylib is under /usr/lib, while the other files are under _$(PCMROOT). Back to the Build Settings on XCode, search for the Other Linker Flags property and add the full path for all these files. Dragging them from Finder works as expected. The resulting list should be similar to the following. Note that the first file, libboost... is unrelated and specific to my project.

Other Linker Flags screenshot

Your application should build successfully at this point.