Java中int和float算术效率的比较

11

我正在编写一个应用程序,使用Dijkstra算法在图中查找最小路径。图中节点和边的权重是float类型的数字,因此算法对浮点数进行了大量的运算。如果将所有权重转换为int类型,能否提高运行时间?在Java中,整数算术运算比浮点数运算更快吗?

我试图编写一个简单的基准测试来验证这一点,但结果并不令我满意。可能编译器已经优化了程序的某些部分,因此结果对我来说并不好。


编辑:

我要解决的问题是信息检索领域的问题。该应用程序应显示作为关键字集合提出的查询的答案。

我的数据结构是加权有向图。给定一组叶子节点,我必须找到连接这些节点的最小树,并向用户显示答案。权重由基于tf/idf技术的加权函数分配。用户不知道我为节点和边分配了哪些权重,他只想看到与他提出的查询相关的答案。因此,不需要精确的结果,只需要根据它们的权重枚举答案的可能性。正如我之前提到的,使用加权函数的原生方法(它基于tf/idf)会得到浮点权重,因此我目前使用了浮点数。

希望这些补充能为问题提供一些背景信息。


我知道整数相乘会快一些,大约快13%,但比较两个整数会慢一些,大约慢22%。 - jutky
我不是完全确定,但对于Dijkstra算法来说,只需要加法和比较操作就足够了。而且对于这些操作,浮点数或整数的差别应该不会太大。我真的很惊讶整数比较会慢22%。请问您进行了什么样的基准测试? - tafa
我正在创建一个随机整数数组和一个随机浮点数数组,然后测量在这些数字上进行比较和乘法操作所需的时间。也许仅迭代数组就占用了大部分时间,因此我想知道是否有关于这个主题的文献资料。 - jutky
7个回答

2

对于简单操作,使用 int 类型更快,但是使用 int 类型可能需要做更多的工作才能得到相同的结果。例如:

作为浮点数

float f = 15 * 0.987;

作为整数

int i = 15 * 987 / 1000;

额外的除法意味着整数运算可能需要更长时间。

在 Dijkstra 算法中,我只是总结和比较路径的权重,因此对于我来说,除法运算非常罕见。你怎么知道对于简单操作,整数更快呢?这是一个普遍的情况还是你可以指引我一些相关文献? - jutky
1
你需要查看JVM生成的本地代码并比较时钟周期。但是,与缓存未命中和系统调用的成本相比,这两个操作都相当快。选择数据类型很可能不会有太大的差异。 - Peter Lawrey

1

在我的机器上,整数减法比双精度减法快大约2.5倍。然而,整数乘法只比双精度乘法快大约1.5倍。

以下测试使用随机数据,可能会防止编译器进行优化。

// test whether int subs are faster than double subs
public void compareIntAndFloatSubtraction(){

    int N = 100000;  // input array size
    int k = 100000;  // number of mathematical operations performed on each element

    // generate random data
    int[] ints = new int[N];
    double[] doubles = new double[N];
    Random r = new Random(1l);
    for (int i = 0; i < N; i++) {
        ints[i] = r.nextInt();
        doubles[i] = r.nextDouble();
    }

    // measure integer subtractions
    long before = System.currentTimeMillis();
    for (int i = 1; i < N; i++) {
        for (int j = 0; j < k; j++) {
            ints[i] -= ints[i-1];  // referring to another element might prevent from optimization also
        }
    }
    System.out.println(String.format("time needed for int subs [ms]: %s", System.currentTimeMillis()-before));

    // measure double subtractions
    before = System.currentTimeMillis();
    for (int i = 1; i < N; i++) {
        for (int j = 0; j < k; j++) {
            doubles[i] -= doubles[i-1];
        }
    }
    System.out.println(String.format("time needed for double subs [ms]: %s", System.currentTimeMillis()-before));

}

1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Henry
1
FYI,我针对“long”数据类型再次运行了测试。减法的结果是:long subs所需时间[ms]:7513,double subs所需时间[ms]:10898。而比较的结果是:long cmp所需时间[ms]:15768,double cmp所需时间[ms]:16012。对于“longs”,平等检查的性能似乎相似。 - Henry
你不能在同一次执行中对不同值类型进行基准测试,否则JVM会过热。 - Marcos Vasconcelos

1

在这种情况下,您应该设定一些性能目标,然后对应用程序进行分析以查看是否符合这些目标。

通常情况下,您可能会发现令人惊讶的结果;基本数字类型几乎不会影响所需时间,或者您的算法是次优的。

关于编译器优化 -- 它们是性能优化的真正和有效的部分。

如果使用类型A在理论上比使用类型B更快,但是您的编译器可以通过优化类型B使其在实际场景中更快,那么这是有价值的证据,而不是失望的来源。


2
我只是想听听,如果我改变应用程序的相当大的部分所需的时间值得我获得的性能提升。但似乎我无法提前确定这一点,检查这一点的最佳方法是实现算法的两个版本并测量运行时间。 - jutky

0

如果你只是想比较重量,你应该选择整数而不是浮点数。


与另一个答案相同的评论:这是一个常见的情况还是您可以指向一些关于该主题的文献。 - jutky

0

通常情况下,你不需要因为性能原因而在intfloat之间做出选择而担心。

以下是Java Puzzlers附录的一段摘录:

浮点运算是不精确的。如果需要精确结果,请勿使用浮点数;相反,请使用整数类型或BigDecimal。如果必须使用浮点运算,则应优先考虑double而非float

除非你有一个非常好的理由,否则如果必须使用浮点运算,通常应该优先考虑double而非float。如果需要精确结果,则可以使用BigDecimal;由于它不是原始类型,所以速度会慢一些,但除非分析表明这是不可接受的,否则这通常是最佳选择。

如果你必须使用浮点运算,那么试图通过使用int进行优化是不明智的。这很可能是一种过早的优化,只会使代码变得更加复杂。以最自然、最易读的方式编写代码。不要为了轻微的性能提升而不必要地复杂化你的代码。

如果你实际上不需要浮点运算,那么尽管使用intlong


请参考以下链接:https://dev59.com/PnE85IYBdhLWcg3w6oB0 和 https://dev59.com/10vSa4cB1Zd3GeqPcCaA。这些链接与程序相关。 - polygenelubricants
我在问题中添加了一些背景信息,希望能澄清一些事情。感谢提供的链接。 - jutky

0

我认为性能在很大程度上取决于算法和软件运行的平台。

如果您在X86平台上进行矩阵/数组计算,则运行时可能会优化它以使用SSE,这是一个仅限于浮点/双精度的扩展指令集。

在其他平台上,运行时可能会优化为OpenCL(我不相信现在有人这样做,但这可能会发生:)。 我不知道在这种平台上哪种类型运行得最快,以及在什么条件下。 它可能只是针对整数工作负载进行了优化。

在这些情况下,我会得出结论,此时优化数据类型(float或int)没有用,只需优化代码的可读性。

如果您的代码非常关键并且您确切地知道系统将在当前和未来的硬件上运行,则可以使用各种算法测试典型工作负载并选择最符合您需求的算法。

但一般来说,只需使用您可以理解的算法,保持代码的可读性,从而使漏洞数量降至最低。如果结果不正确,快速代码并没有那么值得:)


-6

我不这样认为。

浮点数是4字节。Java中的整型也是4字节。

为什么不使用Date(java.util.Date)来获取运行时间呢?

您可以定义一个拥有100,000个节点的图形,然后计算它。


你可能想使用“字节”这个词,而不是“位”。一个4整数只能容纳十六个不同的值... - Donal Fellows
对不起,我的英语很差。所以我用错了单词。(我的母语不是英语)实际上,我认为如果速度比float更快,那是因为硬件的原因。在物理学中,int可能比float更容易实现。 - rainisic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接