为了对你编写的C++循环代码进行profile并计算每次循环消耗的指令周期数,可以采用以下步骤:
- 使用硬件性能计数器
使用 rdtsc 指令
rdtsc(读时间戳计数器)指令可以返回一个64位时间戳计数器的值,这个计数器从系统启动时开始计数,可以用于非常精确的时间测量。你可以在循环的起点和终点分别调用它,然后计算差值来了解每次迭代所消耗的周期数。
#include <iostream>
#include <memory.h>
#include <string.h>
#include <cstdint>
inline uint64_t rdtsc() {
unsigned int lo, hi;
// Serialize
__asm__ __volatile__ ("cpuid" : : : "%rax", "%rbx", "%rcx", "%rdx");
// Get the time-stamp counter
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return (static_cast<uint64_t>(hi) << 32) | lo;
}
void profiled_loop(int v[], int iterations, int &n, int r[]) {
uint64_t start = rdtsc();
for (int i = 0; i < iterations; ++i) {
#if 0
if (v[i] < 1) { r[n++] = i; }
#else
r[n] = i; n += (v[i] < 1);
#endif
}
uint64_t end = rdtsc();
std::cout << "Cycles per iteration: "
<< (end - start) / static_cast<double>(iterations)
<< std::endl;
}
int main() {
const int iterations = 100000000; // Number of loop iterations
int *v = (int *)malloc(sizeof(int) * iterations);
int *k = (int *)malloc(sizeof(int) * iterations);
memset(v, sizeof(int) * iterations, 0);
memset(k, sizeof(int) * iterations, 0);
int n = 0;
for (int i = 0; i < iterations; ++i) {
v[i] = (i % 5 == 0);
}
profiled_loop(v, iterations, n, k);
std::cout << n << std::endl;
return 0;
}
- 高级分析工具
使用 perf 工具 (Linux)
perf 是一个 Linux 性能分析工具,可以对运行时程序进行详细的硬件事件分析,例如 CPU cycles。
编译你的程序:
g++ -o my_program my_program.cpp
使用 perf 工具运行你的程序并收集数据:
perf stat ./my_program
perf stat 将会报告各种性能计数,包括指令周期数。