Java CPU缓存在C编程中无效?

Java CPU缓存在C编程中无效?,java,c++,c,cpu-cache,Java,C++,C,Cpu Cache,这是Linux/GUN下的C程序: #include<stdio.h> #include<sys/time.h> #define Max 1024*1024 int main() { struct timeval start,end; long int dis; int i; int m=0; int a[Max]; gettimeofday(&start,NULL); for(i=0;i<Max;i

这是Linux/GUN下的C程序:

#include<stdio.h>
#include<sys/time.h>
#define Max 1024*1024

int main()
{
    struct timeval start,end;
    long int dis;
    int i;
    int m=0;
    int a[Max];
    gettimeofday(&start,NULL);
    for(i=0;i<Max;i += 1){
            a[Max] *= 3;    
    }   
    gettimeofday(&end,NULL);
    dis = end.tv_usec - start.tv_usec;
    printf("time1: %ld\n",dis);

    gettimeofday(&start,NULL);
    for(i=0;i<Max;i += 16){
            a[Max] *= 3;
    }
    gettimeofday(&end,NULL);
    dis = end.tv_usec - start.tv_usec;
    printf("time2: %ld\n",dis);

    return 0;
}
#包括
#包括
#定义最大1024*1024
int main()
{
结构timeval开始、结束;
长int dis;
int i;
int m=0;
int a[Max];
gettimeofday(&start,NULL);

对于(i=0;i我希望您认识到,在这些测试中,时间单位的差异是10^3。C代码比Java代码快一个数量级

在C代码中应该有
a[i]
而不是
a[Max]

至于缓存:因为您只访问C代码中的一个内存位置(这会触发未定义的行为),所以您的C测试是完全无效的

即使它是正确的,您的方法也是有缺陷的。很有可能C copiler完全跳过了乘法运算,甚至整个循环,因为没有什么取决于它们的结果

第一次运行耗时较长,第二次运行耗时较短。无论如何,数据都必须加载到缓存中,这需要时间。加载数据后,对该数据的操作所需时间较短


Java可能根本不使用缓存(不太可能),或者甚至在执行循环之前就将整个数组预加载到缓存中。这可以解释执行时间相等的原因。

您有三种缓存大小,它们通常是

  • L1:32 KB(数据),4个时钟周期
  • L2:256KB,10-11个时钟周期
  • L3:3-24 MB。40-75个时钟周期
任何大于此值的内容都无法放入缓存,就好像您只是在内存中滚动,就好像它们不在那里一样

我建议您编写一个测试,根据经验计算CPU缓存大小,这是一个很好的练习,可以帮助您理解这一点。顺便说一句,您不需要使用
*=
来练习缓存,因为这可以练习ALU。也许您可以使用一个更简单的操作;)

就Java代码而言,很可能它还没有编译,因此您看到的是interperator的速度,而不是内存访问


我建议您在较小的内存大小上重复运行测试至少2秒,并取平均值。

要查找执行时间,请在
C
code中选择System.nanoTime()而不是System.currentTimeMillis()。语句
a[Max]*=3
将修改数组末尾的内存。您的意思是
a[I]
?是的,这是个错误,a[i]是正确的。+1指出Java结果很可能是伪造的。@StephenC如果在实际用例中,您只需要调用此方法一次就可以获得此数据集大小。在这种情况下,您很可能不关心性能,尤其是在使用选择排序时。@PeterLawrey谢谢,我将尝试一下您的answer
public class Cache1 {
public static void main(String[] args){
    int a[] = new int[1024*1024*64];

    long  time1 = System.currentTimeMillis();
    for(int i=0;i<a.length;i++){
        a[i] *= 3;
    } 
    long time2 = System.currentTimeMillis();
    System.out.println(time2 - time1);

    time1 = System.currentTimeMillis();
    for(int i=0;i<a.length;i += 16){
        a[i] *= 3;
    }
    time2 = System.currentTimeMillis();
    System.out.println(time2 - time1);
}
}