【发布时间】:2014-03-07 10:46:05
【问题描述】:
这是我的 C 程序。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
static int DATA[1024]={1,2,3,4,.....1024};
inline void foo_0(void)
{
int j;
puts("Hello, I'm inside foo_0");
int k=0;
for(j=0;j<1024;j++)
{
//k=DATA[j];
DATA[j]+=1;
}
k+=0;
}
inline void foo_1(void)
{
int j;
puts("Hello, I'm inside foo_1");
int k=0;
for(j=0;j<1024;j+=4)
{
//k=DATA[j];
DATA[j]+=1;
}
k+=0;
}
inline void foo_2(void)
{
int j;
puts("Hello, I'm inside foo_2");
int k=0;
for(j=0;j<1024;j+=16)
{
//k=DATA[j];
DATA[j]+=1;
}
k+=0;
}
inline uint64_t rdtsc()
{
unsigned long a, d;
asm volatile ("cpuid; rdtsc" : "=a" (a), "=d" (d) : : "ebx", "ecx");// core i3/i7
return a | ((uint64_t)d << 32);
}
inline void clflush(volatile void *p)
{
asm volatile ("clflush (%0)" :: "r"(p));
}
int main(void)
{
volatile uint64_t start, end,temp;
unsigned long long total_time=0;
foo_0(); // This will load DATA array into memory
foo_1(); // DATA already loaded into memory
foo_2(); // DATA already loaded into memory
printf("**********************\n");
start=rdtsc();
foo_2();
end=rdtsc();
temp=end-start;
total_time=temp;
printf("Time taken foo_2 = %llu\n",total_time);
start=rdtsc();
foo_1();
end=rdtsc();
temp=end-start;
total_time=temp;
printf("Time taken foo_1 = %llu\n",total_time);
start=rdtsc();
foo_0();
end=rdtsc();
temp=end-start;
total_time=temp;
printf("Time taken foo_0 = %llu\n",total_time);
return 0;
}
输出:
Hello, I'm inside foo_0
Hello, I'm inside foo_1
Hello, I'm inside foo_2
**********************
Hello, I'm inside foo_2
**Time taken foo_2 = 6350**
Hello, I'm inside foo_1
**Time taken foo_1 = 10056**
Hello, I'm inside foo_0
**Time taken foo_0 = 21726**
编辑 1:
当我从所有三个函数中删除 puts() 时,我得到了这个结果
Time taken foo_0 = 16448
Time taken foo_1 = 4438
**********************
Time taken foo_2 = 1548
我期望所有三个 foo_0、foo_1 和 foo_2 的访问时间相同,因为当访问内存以访问整数时,会加载整个缓存块(64 字节是块大小,因此 16 个整数是在缓存块中加载),因此 1、4、16 整数的访问时间必须相同。我没有得到。我在哪里犯错? 我在linux下使用gcc。提前致谢 。
编辑 2
根据 BЈовић 的回答和 Leeor 在评论中的建议,执行时间必须不同,因为在三个不同的函数中执行的加法运算次数不同。尽管在所有三种情况下都没有相同的未命中率,但是执行加法操作的次数各不相同,并且对于所有操作数据都是从缓存中访问(*不是从主存*正如我怀疑的那样)总时间取决于对数组执行的加法操作,而不是缓存未命中/命中。所以我接受BЈовић的回答和Leeor的建议。谢谢大家。
【问题讨论】:
-
杀死所有其他进程,看看你得到了什么
-
@BЈовић ,在关闭所有用户进程并使用 sync 清除 linux 缓存之后; echo 3 > /proc/sys/vm/drop_caches ,我得到了这个结果 耗时 foo_0 = 16532 耗时 foo_1 = 4386 ********************** 耗时foo_2 = 1556 耗时 foo_0 = 16532 耗时 foo_1 = 4412 ************************ 耗时 foo_2 = 1538 [root@localhost 10feb]# ./c foo_0 所用时间 = 16542 foo_1 所用时间 = 4436 ********************** foo_2 所用时间 = 1470
-
为什么在
foo_1()的时间和foo_2()的时间之间打印出一行星号?您的结果在运行之间是否一致?如果您将 all 控制台输出移动到三个调用的计时之后,您会得到类似的结果吗?另外,k+=0;语句的意图是什么? -
@MichaelBurr 我刚刚删除了其他带星号的打印语句,我得到了以下结果- 耗时 foo_0 = 16558 耗时 foo_1 = 4522 耗时 foo_2 = 1394。运行 1-2 次后保持一致。
-
另外,如果我重新排列 foo 函数,我会得到与上面相同的结果。
标签: c linux performance cpu-architecture cpu-cache