2013-06-30 23 views
5

我对微调缓存意识的数据结构(例如参见Michael Spiegel's dissertation或Herlihy等人的hopscotch hashing中的无锁跳跃树)以及防止例如false sharing(例如,在并发阵列处理期间。我已经知道如何通过“sun.arch.data.model”属性找到JVM指针大小,但是我一直无法找到确定L1缓存中的高速缓存行大小的方法。因为我可以继续使用L1行大小的保守估计值(在精确调整缓存意识的数据结构时为64字节,或者防止错误共享时为256字节);因此,这些信息并不重要。但是,如果很容易获得L1缓存属性,那么我也可以使用它。如何从Java进程中找到L1缓存行的大小?

+0

我认为这个(非常有趣,我甚至会说令人兴奋的)任务会花费太多的时间来实现。我会在这里做懒惰的事情:为CPU模型硬编码缓存大小,并确定 - 因为它可能会更容易。但是,如果JVM运行在某种隐藏实际CPU型号的虚拟机内,那么这可能会出错,而您的解决方案将使用该场景的正确大小...... – ppeterka

+0

行大小是行大小;在什么情况下它有64 **和** 256? –

+0

@OliCharlesworth如果我不知道精确的线条大小,那么我会根据我想要完成的工作使用不同的估计值,例如,如果我正在微调一个缓存意识的数据结构,那么我将使用64字节的较低估计值,因为如果实际行大小大于64字节,那么数据结构仍然会运行良好,如果我防止虚假共享,那么我将使用256字节的更高估计值,因为如果实际行大小小于256字节,这仍然会表现良好。 –

回答

1

我已经为Java编写了一个名为CacheSize的小型库,它目前仅支持英特尔处理器。 您可以访问不同层次上缓存的所有信息:

  • 缓存行大小
  • 数套/线
  • associativy
  • 的...

网站here。也可以通过Maven Central获得。

0

你可以做的是一个简单的循环,在给定的步幅从内存中读取单个字节。如果步幅为1(字节),那么每次迭代都需要支付一次线获取罚款。如果你加倍跳过,你可以预期性能的一半,因为你现在每次迭代获取一行两次。

一旦你的步伐达到缓存线的大小,你应该会看到perf的退化停止,因为你会达到你每次迭代获取一次线的水平,并且再次加倍步幅不会改变它,只是跳过线。其中一个问题是,你可能会在你的CPU中触发一个HW流预取程序,并且在某些较低的缓存级别上提前等待你的线路,所以我期望看到斜率减小,但不能完全拉直。在高速缓存行大小的两倍的情况下,这可能会消失,因为你可以通过比它们更快的速度来摆动某些流预取器(还可以有跨步预取器“帮助”你,但影响应该小得多)。

另外请记住,你的代码应该运行在比上一级缓存更大的数据集(比如一个数组)上,几MB应该就足够了。