数组元数据问题(缓存行)

Ben*_*gie 5 .net c#

有一些简单的代码

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());
Run Code Online (Sandbox Code Playgroud)

我的核心2组合需要大约3秒钟.如果我将t1中的索引更改为tmpInt [4],则需要约5.5秒.

无论如何,第一个缓存行在索引4处结束.由于缓存行是64字节而5个int32只是20个字节,这意味着在实际数组之前有44个字节的元数据和/或填充.

我测试的另一组值,其中5和21.5和21需要~3秒,但5和20需要~5.5秒,但这是因为索引20与索引5共享相同的缓存行,因为它们在相同的间隔内64个字节.

所以我的问题是,.Net在数组之前预留了多少数据并且这个数量在32位和64位系统之间变化了吗?

谢谢 :-)

Ron*_*lic 5

当 CPU 尝试加载您的数组并遇到缓存未命中时,它会获取包含您的数组的内存块,但不一定从它开始。.NET 不保证您的数组将缓存对齐。

为了回答您的问题,44 字节的填充主要是来自相关页面的其他数据,这些数据恰好位于同一缓存行中。

编辑http : //msdn.microsoft.com/en-us/magazine/cc163791.aspx似乎表明一个数组有 16 个字节的额外存储空间。4 个字节是同步块索引,4 个字节用于类型句柄元数据,其余的是对象本身。

作为附带评论,很难确切地说错误共享是造成您在这里延迟的原因。这可能是给定的时间,但您应该使用一个好的分析器来检查缓存未命中率。如果它在您给定的情况下跳得很高,您可以非常确定您正在看到虚假共享。