gpt4 book ai didi

java - 使用访问器/ getter 可以更快吗?

转载 作者:行者123 更新时间:2023-12-01 07:32:36 25 4
gpt4 key购买 nike

背景:我计划port a library I have written从C++到Java。该代码处理大小为 nd 维点的列表,并且需要计算标量积等。我想让我的代码独立于点的存储格式和为此目的引入了一个接口(interface),

public interface PointSetAccessor
{
float coord(int p, int c);
}

这允许我获取 p 的第 c 坐标 (0 ≤ c <d) > 第一个点 (0 ≤ p <n)。

问题:由于代码必须非常快,我想知道与 points[p][c] 这样的直接访问模式相比,这是否会降低性能。 ,其中points是一个由 n 个数组组成的数组,每个数组都保存 d 点坐标。

令人惊讶的是,情况恰恰相反:通过 PointSetAccessor 进行“间接”访问,代码(见下文)快了 20% 。 (我使用 time java -server -XX:+AggressiveOpts -cp bin Speedo 进行了测量,前一个版本大约需要 14 秒,后一个版本大约需要 11 秒。)

问题:知道为什么会这样吗?看起来 Hotspot 决定更积极地优化,或者在后一个版本中有更多的自由度?

代码(计算无意义):

public class Speedo
{
public interface PointSetAccessor
{
float coord(int p, int c);
}

public static final class ArrayPointSetAccessor implements PointSetAccessor
{
private final float[][] array;

public ArrayPointSetAccessor(float[][] array)
{
this.array = array;
}

public float coord(int point, int dim)
{
return array[point][dim];
}
}

public static void main(String[] args)
{
final int n = 50000;
final int d = 10;

// Generate n points in dimension d
final java.util.Random r = new java.util.Random(314);
final float[][] a = new float[n][d];
for (int i = 0; i < n; ++i)
for (int j = 0; j < d; ++j)
a[i][j] = r.nextFloat();

float result = 0.0f;
if (true)
{
// Direct version
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; ++j)
{
float prod = 0.0f;
for (int k = 0; k < d; ++k)
prod += a[i][k] * a[j][k];
result += prod;
}
}
else
{
// Accessor-based version
final PointSetAccessor ac = new ArrayPointSetAccessor(a);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; ++j)
{
result += product(ac, d, i, j);
}
}
System.out.println("result = " + result);
}

private final static float product(PointSetAccessor ac, int d, int i, int j)
{
float prod = 0.0f;
for (int k = 0; k < d; ++k)
prod += ac.coord(i, k) * ac.coord(j, k);
return prod;
}
}

最佳答案

这样短的方法,如果它们很热(默认设置下调用超过 10,000 次),将被热点内联,因此您不应该注意到性能差异(测量性能的方式忽略了许多影响,例如热例如,正常运行时间可能会导致错误的结果)。

当运行代码并要求热点显示内联内容时 (-server -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlined),您将得到以下输出,其中显示coordproduct 都内联:

 76    1 %           javaapplication27.Speedo::main @ -2 (163 bytes)   made not entrant
77 6 javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes)
78 7 javaapplication27.Speedo::product (45 bytes)
@ 18 javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes) inline (hot)
@ 27 javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes) inline (hot)
80 2 % javaapplication27.Speedo::main @ 101 (163 bytes)
@ 118 javaapplication27.Speedo::product (45 bytes) inline (hot)
@ 18 javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes) inline (hot)
@ 27 javaapplication27.Speedo$ArrayPointSetAccessor::coord (9 bytes) inline (hot)

关于java - 使用访问器/ getter 可以更快吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16065562/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com