我正在用纯 Java 微调一个数值算法,该算法对每核处理器缓存的大小非常敏感:当工作数据集适合 L1 缓存时,它的运行速度明显更快。
显然,我可以通过一些基准测试为我的本地机器微调它。但理想情况下,我希望能够根据正在使用的处理器的 L1 缓存大小自动调整工作集的大小。
本机代码不是一种选择:用 Java 编写这个算法的全部目的是让它独立于平台!
有没有一种好方法可以可靠地确定纯 Java中每核缓存的大小?
我正在用纯 Java 微调一个数值算法,该算法对每核处理器缓存的大小非常敏感:当工作数据集适合 L1 缓存时,它的运行速度明显更快。
显然,我可以通过一些基准测试为我的本地机器微调它。但理想情况下,我希望能够根据正在使用的处理器的 L1 缓存大小自动调整工作集的大小。
本机代码不是一种选择:用 Java 编写这个算法的全部目的是让它独立于平台!
有没有一种好方法可以可靠地确定纯 Java中每核缓存的大小?
如果使用一组参数时它的运行速度明显快于另一组参数,那么我会根据注意到的差异对其进行调整。在您开始进行大量计算之前(我假设是这种情况,否则您不会关心),运行具有各种不同大小的内部数据存储的较小集合。(我假设算法可以像这样在数字上进行调整。)
这样一来,差异来自 L1 缓存大小,或者可能来自 L1 + L2 缓存大小,或者完全是其他东西并不重要 - 你会选择最适合手头情况的东西。
您需要小心 JIT 预热期,就像在正常的基准测试中一样,但我认为这是创建通用优化方法的好方法,即使它最终会最严重地考虑 L1 缓存.
您可能会将其作为单独的安装时工作,将结果写入配置文件,以便在后续运行时避免额外的工作。(您可能需要一种重新运行调整步骤的方法,以防处理器发生变化或其他情况。)
public class CacheLine {
public static void main(String[] args) {
CacheLine cacheLine = new CacheLine();
cacheLine.startTesting();
}
private void startTesting() {
byte[] array = new byte[128 * 1024];
for (int testIndex = 0; testIndex < 10; testIndex++) {
testMethod(array);
System.out.println("--------- // ---------");
}
}
private void testMethod(byte[] array) {
for (int len = 8192; len <= array.length; len += 8192) {
long t0 = System.nanoTime();
for (int i = 0; i < 10000; i++) {
for (int k = 0; k < len; k += 64) {
array[k] = 1;
}
}
long dT = System.nanoTime() - t0;
System.out.println("len: " + len/1024 + " dT: " + dT + " dT/stepCount: " + (dT) / len);
}
}
}
此代码可帮助您确定 L1 数据缓存大小。您可以在此处详细了解它。 https://medium.com/@behzodbekqodirov/threading-in-java-194b7db6c1de#.kzt4w8eul