我最近用Java写了一个计算密集型算法,然后把它翻译成C++。令我吃惊的是,C++的执行速度要慢得多。我现在已经编写了一个更短的Java测试程序,以及一个相应的C++程序-参见下面。我的原始代码具有大量的数组访问功能,测试代码也是如此。C++的执行时间要长5.5倍(请参阅每个程序末尾的注释)。
以下1st21条评论后的结论...
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执行指令流水线操作,这允许更高的CPU吞吐量。然而,这需要预测下一个要执行的指令是什么。如果猜测错误,必须清除指令管道,并加载正确的指令(这需要时间)。
在编译时,编译器没有足够的信息来预测哪个分支是最有可能的。CPU也会做一些分支预测,但这通常是沿着loops loop和ifs if(而不是else)的路线。
然而,Java的优点是能够在运行时和编译时使用信息。这允许Java将中间分支标识为最频繁出现的分支,并为管道预测该分支。
问题内容: 我有一个2 GB的文件(),其中文件中的每一行都是一个单词,就像: 我需要编写一个程序来读取文件中的每个单词并打印单词计数。我使用Java和C 编写它,但结果令人惊讶:Java运行速度是C 的2.3倍。我的代码如下: C ++: 输出: Java: 输出: 在这种情况下,为什么Java比C 快?如何提高C 的性能? 问题答案: 您不是在比较同一件事。Java程序读取行,以换行符开头,而
为什么我的SIMD向量4长度函数比原始向量长度方法慢3倍? SIMD矢量4长度函数: 幼稚的实现: 我用GCC(Ubuntu7.4.0-1Ubuntu1~18.04.1)7.4.0: SSE版本输出: 纯C版本输出:
问题内容: 以下是C 中的一个简单循环。计时器正在使用QueryPerformanceCounter(),并且非常准确。我发现Java占用了C 60%的时间,这不是吗?我在这里做错了什么?即使是严格的别名(此处未包含在代码中)也完全没有帮助… 此C ++的运行时间约为9.5秒。我正在将Intel Compiler 12.1用于主机处理器优化(专门针对我的处理器),并将所有功能都最大化。所以这是最好
问题内容: 我发现这一点的同时解决问题205的项目欧拉。问题如下: 彼得有九个四面(金字塔形)骰子,每个骰子的编号分别为1、2、3、4。科林有六个六边形(立方)骰子,每个骰子的编号为1、2、3、4、5、6。 彼得和科林掷骰子并比较总数:最高的总胜利数。如果总数相等,则结果为平局。 金字塔形皮特击败立方柯林的概率是多少?以0.abcdefg的形式将答案四舍五入到小数点后七个位 我用番石榴写了一个幼稚
问题内容: 没有迅速的方法。该程序必须从某处开始执行。那么快速代码执行的切入点是什么,它是如何确定的? 问题答案: 普通Swift模块中的入口点是模块中名为的文件。是唯一一个允许在顶层具有表达式和语句的文件(模块中的所有其他Swift文件只能包含声明)。 可可触摸使用属性上的实现,而不是一个纪念的入口点文件。可可曾经使用了一个简单的最小文件,但是从Xcode 6.1开始, 它在的实现上使用属性。
在运行一个数字积分器时,我注意到根据我在字典中提取字段值的方式,速度有明显的不同 在我的系统上,我注意到以下差异(使用 iPython) 相比于 这似乎是一个很小的差异,但是对于某些阵列来说,这种差异甚至更大。是什么导致了这种行为,有什么方法可以改变我对< code>get()函数的使用吗?