Java CPU缓存在C编程中无效?
这是Linux/GUN下的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
#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);
}
}