我有一段代码,在我运行的每个测试中,函数调用都会产生大量开销。代码是一个紧密的循环,对数组的每个元素(包含 4-8 百万int
)执行一个非常简单的函数。
运行代码,主要包括
for (int y = 1; y < h; ++y) {
for (int x = 1; x < w; ++x) {
final int p = y * s + x;
n[p] = f.apply(d, s, x, y);
}
}
执行类似的东西
(final int[] d, final int s, final int x, final int y) -> {
final int p = s * y + x;
final int a = d[p] * 2
+ d[p - 1]
+ d[p + 1]
+ d[p - s]
+ d[p + s];
return (1000 * (a + 500)) / 6000;
};
在各种机器上(我的工作笔记本电脑、带有 i7 3840QM 的 W530、带有 Xeon E5-1620 一个核心的服务器 VM 和一个带有未知 CPU 核心的 Digital Ocean 节点),当调用方法与内联。所有测试均在 Java 1.8.0_11(Java HotSpot(TM) 64 位服务器 VM)上执行。
工作机器:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 40.860 0.184 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 22.603 0.159 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 22.792 0.117 ops/s
专用服务器,虚拟机:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 40.685 0.224 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 16.077 0.113 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 23.827 0.088 ops/s
做VPS:
Benchmark Mode Samples Score Score error Units
c.s.q.ShaderBench.testProcessInline thrpt 200 24.425 0.506 ops/s
c.s.q.ShaderBench.testProcessLambda thrpt 200 9.643 0.140 ops/s
c.s.q.ShaderBench.testProcessProc thrpt 200 13.733 0.134 ops/s
所有可接受的性能,但我有兴趣弄清楚为什么调用有如此大的开销以及可以做些什么来优化它。目前正在试验不同的参数集。
内联所有潜在的操作会很困难,但理论上是可能的。对于接近 2 倍的性能提升,这可能是值得的,但维护将是一场噩梦。
我不确定是否有合理的方法来批量处理一组重复;大多数操作采用多个输入(调用者不知道)并产生单个输出。
我还有哪些其他选择可以最小化开销和平衡性能?