java - 与 java 相比,为什么这个 C++ 代码执行速度如此之慢?

标签 java c++ performance

我最近用 Java 编写了一个计算密集型算法,然后将其翻译成 C++。令我惊讶的是,C++ 的执行速度相当慢。我现在已经编写了一个更短的 Java 测试程序和一个相应的 C++ 程序 - 见下文。我的原始代码以大量数组访问为特色,测试代码也是如此。 C++ 的执行时间要长 5.5 倍(请参阅每个程序末尾的注释)。

在 1st 21 条评论后的结论 ...

测试代码:

  1. g++ -o ... Java 快 5.5 倍
  2. g++ -O3 -o ... Java 快 2.9 倍
  3. g++ -fprofile-generate -march=native -O3 -o ...(运行,然后 g++ -fprofile-use 等)Java 快 1.07 倍。

我的原始项目(比测试代码复杂得多):

  1. Java 快 1.8 倍
  2. C++ 快 1.9 倍
  3. C++ 快 2 倍
Software environment:
    Ubuntu 16.04 (64 bit).
    Netbeans 8.2 / jdk 8u121 (java code executed inside netbeans)
    g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
    Compilation: g++ -o cpp_test cpp_test.cpp

Java代码:

public class JavaTest {
    public static void main(String[] args) {
        final int ARRAY_LENGTH = 100;
        final int FINISH_TRIGGER = 100000000;
        int[] intArray = new int[ARRAY_LENGTH];
        for (int i = 0; i < ARRAY_LENGTH; i++) intArray[i] = 1;
        int i = 0;
        boolean finished = false;
        long loopCount = 0;
        System.out.println("Start");
        long startTime = System.nanoTime();
        while (!finished) {
            loopCount++;
            intArray[i]++;
            if (intArray[i] >= FINISH_TRIGGER) finished = true;
            else if (i <(ARRAY_LENGTH - 1)) i++;
            else i = 0;
        }
        System.out.println("Finish: " + loopCount + " loops; " +
            ((System.nanoTime() - startTime)/1e9) + " secs");
        // 5 executions in range 5.98 - 6.17 secs (each 9999999801 loops)
    }
}

C++代码:

//cpp_test.cpp:
#include <iostream>
#include <sys/time.h>
int main() {
    const int ARRAY_LENGTH = 100;
    const int FINISH_TRIGGER = 100000000;
    int *intArray = new int[ARRAY_LENGTH];
    for (int i = 0; i < ARRAY_LENGTH; i++) intArray[i] = 1;
    int i = 0;
    bool finished = false;
    long long loopCount = 0;
    std::cout << "Start\n";
    timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    long long startTime = (1000000000*ts.tv_sec) + ts.tv_nsec;
    while (!finished) {
        loopCount++;
        intArray[i]++;
        if (intArray[i] >= FINISH_TRIGGER) finished = true;
        else if (i < (ARRAY_LENGTH - 1)) i++;
        else i = 0;
    }
    clock_gettime(CLOCK_REALTIME, &ts);
    double elapsedTime =
        ((1000000000*ts.tv_sec) + ts.tv_nsec - startTime)/1e9;
    std::cout << "Finish: " << loopCount << " loops; ";
    std::cout << elapsedTime << " secs\n";
    // 5 executions in range 33.07 - 33.45 secs (each 9999999801 loops)
}

最佳答案

我唯一一次让 C++ 程序跑赢 Java 是在使用分析信息时。这表明运行时信息(Java 默认获取)中有些东西可以加快执行速度。

除了重要的 if 语句外,您的程序中没有太多内容。也就是说,如果不分析整个程序,就很难预测哪个分支最有可能。这让我相信这是一个分支预测错误的问题。现代 CPU 做 instruction pipelining这允许更高的 CPU 吞吐量。然而,这需要预测下一条要执行的指令是什么。如果猜测错误,则必须清除指令流水线,并加载正确的指令(这需要时间)。

在编译时,编译器没有足够的信息来预测哪个分支最有可能。 CPU 也会做一些分支预测,但这通常是沿着循环 loop 和 ifs if(而不是 else)的思路。

然而,Java 具有能够在运行时和编译时使用信息的优势。这允许 Java 将中间分支识别为最常出现的分支,因此可以为管道预测该分支。

关于java - 与 java 相比,为什么这个 C++ 代码执行速度如此之慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44342884/

相关文章:

java - 我见过的最奇怪的tomcat错误

c++ - 模板类的组成

c++ - 如何在动态库(/MD)项目中使用静态库(/MT)?

algorithm - 自适应IO优化问题

python - 如何使 while 迭代更快?

java - Adobe Acrobat 在 java 中拦截调用 BasicService.showDocument() 的每个 URL

java - 如何加载文件并将其保存在 Android 的对象列表中?

java - EJB 应用程序关闭钩子(Hook)

c++ - 访问基类型数组成员(Int-to-Type 习语)

mysql - 具有较大 LIMIT 范围的 ORDER BY 查询非常慢