gpt4 book ai didi

c++ - 测量 C++ 代码的 CPU 周期

转载 作者:搜寻专家 更新时间:2023-10-31 01:40:07 25 4
gpt4 key购买 nike

我的目标是使用简单的代码来衡量(不同的)缓存的效果。我正在关注这篇文章,特别是第 20 和 21 页: https://people.freebsd.org/~lstewart/articles/cpumemory.pdf

我正在使用 64 位 Linux。 L1d缓存32K,L2缓存256K,L3缓存25M。

这是我的代码(我用没有标志的 g++ 编译这段代码):

#include <iostream>

// ***********************************
// This is for measuring CPU clocks
#if defined(__i386__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned long long int x;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc(void)
{
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
#endif
// ***********************************


static const int ARRAY_SIZE = 100;

struct MyStruct {
struct MyStruct *n;
};

int main() {
MyStruct myS[ARRAY_SIZE];
unsigned long long cpu_checkpoint_start, cpu_checkpoint_finish;

// Initializing the array of structs, each element pointing to the next
for (int i=0; i < ARRAY_SIZE - 1; i++){
myS[i].n = &myS[i + 1];
for (int j = 0; j < NPAD; j++)
myS[i].pad[j] = (long int) i;
}
myS[ARRAY_SIZE - 1].n = NULL; // the last one
for (int j = 0; j < NPAD; j++)
myS[ARRAY_SIZE - 1].pad[j] = (long int) (ARRAY_SIZE - 1);

// Filling the cache
MyStruct *current = &myS[0];
while ((current = current->n) != NULL)
;

// Sequential access
current = &myS[0];

// For CPU usage in terms of clocks (ticks)
cpu_start = rdtsc();

while ((current = current->n) != NULL)
;

cpu_finish = rdtsc();

unsigned long long avg_cpu_clocks = (cpu_finish - cpu_start) / ARRAY_SIZE;

std::cout << "Avg CPU Clocks: " << avg_cpu_clocks << std::endl;
return 0;
}

我有两个问题:

1- 我将 ARRAY_SIZE 从 1 变为 1,000,000(因此我的数组大小在 2B 到 2MB 之间),但平均 CPU 时钟始终为​​ 10。

根据该 PDF(第 21 页的图 3-10),当阵列完全适合 L1 时,我预计会获得 3-5 个时钟,而当它超过 L1 的大小时,我会获得更高的数字(9 个周期)。

2- 如果我将 ARRAY_SIZE 增加到超过 1,000,000,我将出现段错误(核心已转储),这是由于堆栈溢出造成的。我的问题是使用动态分配 (MyStruct *myS = new MyStruct[ARRAY_SIZE]) 是否不会导致任何性能损失。

最佳答案

This is my code (I compile this code with g++ with no flags)

如果不传-O3,那么while ((current = current->n) != NULL)会被编译成多次内存访问,不是一个单一的加载指令。通过传递-O3,循环将被编译成:

.L3:
mov rax, QWORD PTR [rax]
test rax, rax
jne .L3

如您所料,这将在每次迭代中运行 4 个周期。

请注意,您可以使用 __rdtsc 内部编译器代替内联汇编。请参阅:Get CPU cycle count? .

关于c++ - 测量 C++ 代码的 CPU 周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30196766/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com