在代碼中使用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可執行文件,得到統計結果。

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