基准测试时如何使缓存无效?
-
30-09-2019 - |
题
我有此代码,即交换使用和使用cast的顺序时,它们的性能也交换。
using System;
using System.Diagnostics;
using System.Linq;
using System.IO;
class Test
{
const int Size = 30000000;
static void Main()
{
object[] values = new MemoryStream[Size];
UsingAs(values);
UsingCast(values);
Console.ReadLine();
}
static void UsingCast(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
if (o is MemoryStream)
{
var m = (MemoryStream)o;
sum += (int)m.Length;
}
}
sw.Stop();
Console.WriteLine("Cast: {0} : {1}", sum,
(long)sw.ElapsedMilliseconds);
}
static void UsingAs(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
if (o is MemoryStream)
{
var m = o as MemoryStream;
sum += (int)m.Length;
}
}
sw.Stop();
Console.WriteLine("As: {0} : {1}", sum,
(long)sw.ElapsedMilliseconds);
}
}
输出:
As: 0 : 322
Cast: 0 : 281
这样做...
UsingCast(values);
UsingAs(values);
...结果:
Cast: 0 : 322
As: 0 : 281
做这个...
UsingAs(values);
...结果:
As: 0 : 322
做到这一点时:
UsingCast(values);
...结果:
Cast: 0 : 322
除了独立运行它们之外,如何 无效 缓存因此以基准为基准的第二个代码不会收到第一个代码的缓存内存吗?
除了基准测试,只是喜欢现代处理器做这个缓存魔术的事实:-)
编辑
建议(据称)尝试此更快的代码...
static void UsingAsAndNullTest(object[] values)
{
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in values)
{
var m = o as MemoryStream;
if (m != null)
{
sum += (int)m.Length;
}
}
sw.Stop();
Console.WriteLine("As and null test: {0} : {1}", sum,
(long)sw.ElapsedMilliseconds);
}
...结果是:
As and null test: 0 : 342
比上面的两个代码慢
编辑]:
如建议将每个例程交给自己的副本...
static void UsingAs(object[] values)
{
object[] a = values.ToArray();
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in a)
{
if (o is MemoryStream)
{
var m = o as MemoryStream;
sum += (int)m.Length;
}
}
sw.Stop();
Console.WriteLine("As: {0} : {1}", sum,
(long)sw.ElapsedMilliseconds);
}
static void UsingCast(object[] values)
{
object[] a = values.ToArray();
Stopwatch sw = Stopwatch.StartNew();
int sum = 0;
foreach (object o in a)
{
if (o is MemoryStream)
{
var m = (MemoryStream)o;
sum += (int)m.Length;
}
}
sw.Stop();
Console.WriteLine("Cast: {0} : {1}", sum,
(long)sw.ElapsedMilliseconds);
}
...输出:
Cast: 0 : 282
As: 0 : 282
现在,他们取得了相同的结果,谢谢Remus!
运行铸件,并且独立地产生相同的结果(即282)。现在,至于为什么他们成为 快点 (从322降至282毫秒)当它们被递给自己的数组副本时,我无法从中做任何东西:-)完全是另一个故事
解决方案
如果您想从图片中取出L2缓存和TLB错过,则只需在相同大小的不同内存线上调用第二个测试即可。
不隶属于 StackOverflow