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
Download Intel PCM here and extract it wherever you like to keep your libraries and packages. I’ll refer to this directory as _$(PCMROOT).
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).
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
MSRKernel.h will be copied to
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.
.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:
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 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.
Your application should build successfully at this point.