C# 生成CPU缓存未命中时的性能
我试图了解.NET世界中的CPU缓存性能。具体来说,我是通过伊戈尔·奥斯托夫斯基的 我已经阅读了他文章中的前三个例子,并记录了与他有很大不同的结果。我想我一定是做错了什么,因为我机器上的性能显示的结果与他在文章中显示的结果几乎完全相反。我没有看到缓存未命中所带来的预期效果 我做错了什么?(错误的代码、编译器设置等) 以下是我的机器上的性能结果: 如果有帮助,我机器上的处理器是Intel Core i7-2630QM。以下是有关我的处理器缓存的信息: 我已经在x64发布模式下编译 下面是我的源代码:C# 生成CPU缓存未命中时的性能,c#,.net,arrays,performance,cpu-cache,C#,.net,Arrays,Performance,Cpu Cache,我试图了解.NET世界中的CPU缓存性能。具体来说,我是通过伊戈尔·奥斯托夫斯基的 我已经阅读了他文章中的前三个例子,并记录了与他有很大不同的结果。我想我一定是做错了什么,因为我机器上的性能显示的结果与他在文章中显示的结果几乎完全相反。我没有看到缓存未命中所带来的预期效果 我做错了什么?(错误的代码、编译器设置等) 以下是我的机器上的性能结果: 如果有帮助,我机器上的处理器是Intel Core i7-2630QM。以下是有关我的处理器缓存的信息: 我已经在x64发布模式下编译 下面是我
class Program
{
static Stopwatch watch = new Stopwatch();
static int[] arr = new int[64 * 1024 * 1024];
static void Main(string[] args)
{
Example1();
Example2();
Example3();
Console.ReadLine();
}
static void Example1()
{
Console.WriteLine("Example 1:");
// Loop 1
watch.Restart();
for (int i = 0; i < arr.Length; i++) arr[i] *= 3;
watch.Stop();
Console.WriteLine(" Loop 1: " + watch.ElapsedMilliseconds.ToString() + " ms");
// Loop 2
watch.Restart();
for (int i = 0; i < arr.Length; i += 32) arr[i] *= 3;
watch.Stop();
Console.WriteLine(" Loop 2: " + watch.ElapsedMilliseconds.ToString() + " ms");
Console.WriteLine();
}
static void Example2()
{
Console.WriteLine("Example 2:");
for (int k = 1; k <= 1024; k *= 2)
{
watch.Restart();
for (int i = 0; i < arr.Length; i += k) arr[i] *= 3;
watch.Stop();
Console.WriteLine(" K = "+ k + ": " + watch.ElapsedMilliseconds.ToString() + " ms");
}
Console.WriteLine();
}
static void Example3()
{
Console.WriteLine("Example 3:");
for (int k = 1; k <= 1024*1024; k *= 2)
{
//256* 4bytes per 32 bit int * k = k Kilobytes
arr = new int[256*k];
int steps = 64 * 1024 * 1024; // Arbitrary number of steps
int lengthMod = arr.Length - 1;
watch.Restart();
for (int i = 0; i < steps; i++)
{
arr[(i * 16) & lengthMod]++; // (x & lengthMod) is equal to (x % arr.Length)
}
watch.Stop();
Console.WriteLine(" Array size = " + arr.Length * 4 + " bytes: " + (int)(watch.Elapsed.TotalMilliseconds * 1000000.0 / arr.Length) + " nanoseconds per element");
}
Console.WriteLine();
}
}
类程序
{
静态秒表=新秒表();
静态int[]arr=新int[64*1024*1024];
静态void Main(字符串[]参数)
{
例1();
例2();
例3();
Console.ReadLine();
}
静态无效示例1()
{
Console.WriteLine(“示例1:”);
//回路1
watch.Restart();
对于(int i=0;i 对于(int k=1;k为什么在第二个循环中使用i+=32。您正以这种方式跨过缓存线。32*4=128字节比需要的64字节大得多。您使用的是什么CPU?它有多少缓存?级别1和2?它是Intel Core i7-2630QM。缓存统计数据在上面的命令行映像中。此外,您在系统中有足够的RAM?在测试过程中,你没有在页面文件上乱动?我的机器上有8 GB的RAM。当运行这个控制台应用程序时,RAM的使用量永远不会超过4GB。你可以放心地假设作者没有你那么好的内核。测试循环固有的1/K性能强调了他的结果,但混淆了你的结果……我不明白这个答案。为什么这是否解释了数量级的差异,以及这与第二次或第三次测试有什么关系?即使知道这是非常古老的,只是供其他人参考,缓存线通常是以64字节的块获取的,因此DiVan显示的是以int(4字节)表示的数组,无论您以32步遍历它,最终都会跳过多个缓存线,这当然会使循环2更快,如果您使用的是16而不是32(16x4=64),那么您不会跳过任何缓存线,循环1和2将得到类似的结果,即使循环2的迭代次数少于循环1。