c - 使用 RDTSC 访问内存中的 ARRAY 时在 C 中出现意外输出

标签 c linux performance cpu-architecture cpu-cache

这是我用 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 的访问时间相同,因为当访问内存以访问一个整数时,整个缓存 block 被加载(64 字节是 block 大小,所以 16 个整数是加载到缓存 block 中),因此 1、4、16 整数的访问时间必须相同。我不明白那个。我在哪里犯错? 我在linux下使用gcc。提前致谢 。

编辑 2

根据 BЈовић 的回答和 Leeor 在评论中的建议,执行时间必须不同,因为在三个不同的函数中执行的加法运算次数不同。虽然在所有三种情况下都没有未命中,但是加法运算的执行次数各不相同,并且对于所有操作数据都是从缓存访问的(*不是从主内存*正如我所怀疑的那样)总时间取决于对数组执行的加法操作的数量,而不是缓存未命中/命中。所以我接受 BЈовић 的回答和 Leeor 的建议。谢谢大家。

最佳答案

1) 您的进程正在被其他进程推到后台,因此无法获得准确的时间。

2) 由于循环不同,时间不可能相同:

foo_0() : for(j=0;j<1024;j++)
foo_1():for(j=0;j<1024;j+=4)
foo_2() : for(j=0;j<1024;j+=16)

关于c - 使用 RDTSC 访问内存中的 ARRAY 时在 C 中出现意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21671521/

相关文章:

c - 为什么uva 100问题超出了时间限制

linux - 无法在 Linux 上找到 libxlutil.so.1.0

iphone - 优化 iPhone OpenGL ES 填充率

c - 有没有办法识别 C 项目中所有未使用的全局变量?

c - 当我们在 C 的调用函数中不使用 return 语句时会发生什么?

C编程: Hash Key (uint32) generation ( Inputs : one uint32 and one uint64 to generate unique key)

linux - 本地主机和主机名上的 ab 测试有区别吗?

linux - 拥有 Linux 思维框架对成为更好的嵌入式程序员有帮助吗?

python - 对称矩阵的 LDL^T 分解的 Numpy 数组乘法

MySQL INSERT INTO 查询在 C 中太慢