在代码中使用PCM(Processor Counter Monitor)

PCM功能简介:

Intel-pcm提供了一系列监控CPU核心、Cache、内存控制器和内存DIMM芯片的硬件事件次数,相关寄存器值,硬件性能指标的接口。

主要内容:

主要对外的类和接口集中定义在文件cpucounters.h,代码地址为 https://github.com/opcm/pcm

  • 定义了核心PCM类和四种系统状态类,即SystemCounterStateSocketCounterStateCoreCounterStateServerUncorePowerState
  • 定义了获取系统状态的三类接口。
    • 获取当前整个系统范围的状态:SystemCounterState getSystemCounterState()
    • 获取当前某个CPU插槽(socket)范围的状态:SocketCounterState getSocketCounterState(uint32 socket)
    • 获取当前某个CPU(逻辑)核心范围的状态:CoreCounterState getCoreCounterState(uint32 core)
  • 实现了获取一段时间内以及特定时刻硬件事件的计数接口。
    • 时钟周期:获得期间内DRAM和多通道DRAM(MCDRAM),能量控制单元PCU和快速通道互联(QPI)的时钟周期数。例如getDRAMClocks, getMCDRAMClocks, getPCUClocks, getQPIClocks
    • Performance Monitor Unit (PMU)计数器:获得期间内内存控制器MC,能量控制单元PCU,以及嵌入式DRAM控制器的PMU计数器值。例如:getMCCounter, getPCUCounter, getEDCCounter
    • Cache访问:获得期间内L2和L3 Cache的命中/缺失率、Miss数量,此外还能统计L3 Cache的占空比,L3 Cache访问命中次数中由Snoop协议引发的数量。例如getL2CacheHits, getL2CacheHitRatio, getL3CacheMisses, getL3CacheOccupancy, getL3CacheHitsSnoop
    • Memory传输
      获得期间内内存传输带宽,处理器从各种内存(包括DRAM、Persistent Memory和嵌入式DRAM)中读取/写回的字节总数,对内存的IO请求字节数。例如getLocalMemoryBW, getBytesReadFromMC, getBytesWrittenToMC, getIORequestBytesFromMC
    • 处理器核心:获得期间内单个处理器核心/整个系统的IPC、退役指令数、时钟周期数和平均时钟频率。例如getIPC, getInstructionsRetire, getExecUsage, getCycles, getAverageFrequency
    • 能耗:获得期间内处理器和DRAM的耗能数量。例如getConsumedEnergy, getDRAMConsumedEnergy, getConsumedJoules
    • Quick-Path Interconnect (QPI): 获得期间内QPI不同QPI连接之间的数据传输量。例如getIncomingQPILinkBytes, getOutgoingQPILinkBytes

使用示例:

  • 编译PCM库,在linux环境下使用make命令编译后会在编译目录下生成libPCM.a静态链接库。

  • 统计示例代码造成的L3 Miss和DRAM读写数量,示例代码如下:

  /* filename: test.cc */
#include <iostream>
#include <cstdint>
#include "cpucounters.h"

using std::cout;
int main(void) {
    //新建一个PCM实例
    PCM* pcm_ = PCM::getInstance();
    auto status = pcm_->program();
    const int TEST_SCALE = 10000;
    int * arr = new int[TEST_SCALE];
    uint32_t check_sum = 0;
    //我们希望监控整个系统的硬件数值
    SystemCounterState before_sstate = getSystemCounterState();
        for(int i = 0; i < TEST_SCALE; i++) {
            check_sum = (check_sum + arr[i]) % (1 << 16 - 1);
        }
    SystemCounterState after_sstate = getSystemCounterState();
    // 获取区间内的统计数值
    std::cout << "\tL3 misses: " << getL3CacheMisses(before_sstate, after_sstate) << "\n"
              << "\tDRAM Reads (bytes): " << getBytesReadFromMC(before_sstate, after_sstate) << "\n"
              << "\tDRAM Writes (bytes): " << getBytesWrittenToMC(before_sstate, after_sstate) << "\n";

	delete []arr;
	return 0;
}
  • 使用命令编译示例代码 g++ test.cc -Ipcm -Lpcm -lPCM -pthread -o test编译test.cc,其中-I选项添加头文件目录pcm,-L选项添加链接库目录pcm,-l 选项指定静态链接库libPCM.a。

  • 编译生成后使用命令modprobe msr提供访问Model-Specific Register,MSR的访问权限。

  • 在root权限下运行test可执行文件,得到统计结果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章