获得了一些简单的代码
Int32[] tmpInt = new Int32[32];
long lStart = DateTime.Now.Ticks;
Thread t1 = new Thread(new ThreadStart(delegate()
{
for (Int32 i = 0; i < 100000000; i++)
Interlocked.Increment(ref tmpInt[5]);
}));
Thread t2 = new Thread(new ThreadStart(delegate()
{
for (Int32 i = 0; i < 100000000; i++)
Interlocked.Increment(ref tmpInt[20]);
}));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
Console.WriteLine(((DateTime.Now.Ticks - lStart)/10000).ToString());
我的核心2组合需要大约3秒钟。如果我将t1中的索引更改为tmpInt [4],则需要约5.5秒。
无论如何,第一个缓存行在索引4处结束。由于缓存行是64字节而5个int32s只有20个字节,这意味着在实际数组之前有44个字节的元数据和/或填充。
我测试的另一组值,其中5和21.5和21需要~3秒,但5和20需要~5.5秒,但这是因为索引20与索引5共享相同的缓存行,因为它们是间隔的在相同的64个字节内。
所以我的问题是,.Net在数组之前预留了多少数据,这个数量在32位和64位系统之间是否会发生变化?
谢谢: - )
答案 0 :(得分:4)
当CPU尝试加载您的阵列并且遇到缓存未命中时,它会获取包含您的阵列的内存块,但不一定是STARTING。 .NET不保证您的数组将与缓存对齐。
要回答您的问题,44个字节的填充主要是来自关联页面的其他数据,这些数据恰好位于同一个缓存行中。
编辑:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx似乎表明数组有16个字节的额外存储空间。 4个字节是同步块索引,4个字节用于类型句柄元数据,其余的是对象本身。
作为一个评论,很难确切地说,错误分享是造成你的延迟的原因。可能会给出时间,但你应该使用一个好的分析器来检查缓存未命中率。如果它因你的情况而跳得很高,你可以非常肯定你在游戏中看到了虚假分享。
答案 1 :(得分:0)
除了答案: https://stackoverflow.com/a/1589806/543814
我的测试表明我期望的是32位[64位]:
总之,有4种可能性:
12 bytes (32-bit value array)
16 bytes (32-bit reference array)
20 bytes (64-bit value array)
28 bytes (64-bit reference array)
我过去遗漏的东西:在具有项目设置的64位计算机上,更喜欢32位&#39;启用(默认), 32位适用!