性能优化:C++;vs Java未按预期执行 我编写了两个程序,用于实现矩阵乘法的简单算法,一个是C++,一个是java。与我的预期相反,java程序比C++程序运行速度快2.5X。我是C++初学者,希望能在C++程序中改变什么,使它运行得更快。
我的程序从这篇博文中借用代码和数据 以下是我正在使用的当前编译标志:性能优化:C++;vs Java未按预期执行 我编写了两个程序,用于实现矩阵乘法的简单算法,一个是C++,一个是java。与我的预期相反,java程序比C++程序运行速度快2.5X。我是C++初学者,希望能在C++程序中改变什么,使它运行得更快。,java,c++,performance,optimization,Java,C++,Performance,Optimization,我的程序从这篇博文中借用代码和数据 以下是我正在使用的当前编译标志: g++ -O3 main.cc javac Main.java 以下是当前的编译器/运行时版本: $ g++ --version g++.exe (GCC) 4.8.1 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO
g++ -O3 main.cc
javac Main.java
以下是当前的编译器/运行时版本:
$ g++ --version
g++.exe (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)
我的电脑是~2012年的core i3笔记本电脑,运行windows和MinGW。以下是当前的性能结果:
$ time ./a.exe < ../Testing/2000.in
507584919
real 0m36.469s
user 0m0.031s
sys 0m0.030s
$ time java Main < ../Testing/2000.in
507584919
real 0m14.299s
user 0m0.031s
sys 0m0.015s
$time./a.exe<../Testing/2000.in
507584919
实数0m36.469s
用户0m0.031s
系统0m0.030s
$time java Main<../Testing/2000.in
507584919
真实0m14.299s
用户0m0.031s
系统0m0.015s
这里是C++程序:
#include <iostream>
#include <cstdio>
using namespace std;
int *A;
int *B;
int height;
int width;
int * matMult(int A[], int B[]) {
int * C = new int[height*width];
int n = height;
for (int i = 0; i < n; i++) {
for (int k = 0; k < n; k++) {
for (int j = 0; j < n; j++) {
C[width*i+j]+=A[width*i+k] * B[width*k+j];
}
}
}
return C;
}
int main() {
std::ios::sync_with_stdio(false);
cin >> height;
cin >> width;
A = new int[width*height];
B = new int[width*height];
for (int i = 0; i < width*height; i++) {
cin >> A[i];
}
for (int i = 0; i < width*height; i++) {
cin >> B[i];
}
int *result = matMult(A,B);
cout << result[2];
}
#包括
#包括
使用名称空间std;
int*A;
int*B;
内部高度;
整数宽度;
int*matMult(int A[],int B[]{
int*C=新int[高度*宽度];
int n=高度;
对于(int i=0;i>高度;
cin>>宽度;
A=新整数[宽度*高度];
B=新整数[宽度*高度];
对于(int i=0;i>A[i];
}
对于(int i=0;i>B[i];
}
int*result=matMult(A,B);
cout我无法分析java执行,因为它创建了一个临时的可执行模块,该模块在“使用”后消失。但是,我假设它确实执行SSE指令以获得该速度[或者它展开循环,如果禁用SSE指令,clang++会这样做]
但是使用g++(4.9.2)和clang++编译时,我可以清楚地看到,clang优化了循环以使用SSE指令,而gcc没有。因此,生成的代码的速度要慢4倍。更改代码以便在每个维度中使用2000的常量值[因此编译器“知道”高度和宽度的维度],gcc编译器生成的代码大约需要8秒(在我的机器上!),相比之下,使用“变量”值生成的代码需要27秒(在这里,铿锵编译的代码也稍微快一点,但我可以说是在噪音范围内)
<> P.结论:编译器的质量/聪明将对紧环的性能产生很大的影响。代码越复杂和变化,C++解决方案越可能产生更好的代码,简单而易于编译的问题在java代码中可能会更好(通常是,但不能保证)。例如,我希望java编译器使用评测来确定循环的数量
编辑:
time
的结果可用于确定读取文件是否花费了很长时间,但您需要某种分析工具来确定实际输入是否占用了大量CPU时间等
java引擎使用一个“即时编译器”,它使用剖析来确定特定代码片段命中的次数(你也可以为C++做这件事,而大项目经常这样做!)它允许它在一个循环中展开循环,或者在运行时确定循环的次数。因为这个代码执行2000×2000×2000循环,而C++编译器在知道这些值的大小告诉我们java运行时实际上没有做得更好(至少不是最初)时,实际上做得更好。,只是随着时间的推移,它成功地提高了性能
不幸的是,由于java运行时的工作方式,它没有留下二进制代码,因此我无法真正分析它的功能
这里的关键是,你所做的实际操作很简单,逻辑很简单,只是很多,而且你使用的是简单的实现。java和C++都会从手动展开循环中受益,例如:
< P> <强> C++默认的速度不比java < /强>
C++作为一种语言是很快的,但是一旦你将库合并到混合中,你就注定了这些库的速度
该标准很难为性能和周期而构建。标准库的编写考虑了设计和正确性
C++为您提供了优化的机会!
如果您对标准库的性能不满意,您可以而且应该使用自己的优化版本
例如,标准C++ ++对象在设计(流、区域、刻面、内部缓冲区)时很漂亮,但是这使得它们在性能上很差。
如果您是为Windows操作系统编写的,则可以使用ReadFile
和WriteConsole
作为IO机制。
如果您切换到这些函数而不是标准库,那么您的程序的性能会比Java好几个数量级。您是否实际测量过这两种情况下加载文件的时间?刚刚测量过。将发布上述结果。两个程序看起来都不是特别“快”在java代码中,使用正则表达式似乎特别有助于使它慢下来。一般来说,我认为MICOCOBITICONDEX是一个坏主意。@ MatsPetersson,我同意。C++中的缓冲区值读很可能比java中的缓冲线读慢。这看起来像是一个愚蠢的问题,但是你总是检查C++ P吗?首先,java程序,当java程序运行时,它可以把输入文件放在缓存中。Mats,谢谢你的回答。我做了你建议的修改——HalcDead 2000的高度和宽度。在这种情况下C++在我的计算机上运行8秒,比原来快4倍。
import java.util.*;
import java.io.*;
public class Main {
static int[] A;
static int[] B;
static int height;
static int width;
public static void main(String[] args) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
height = Integer.parseInt(reader.readLine());
width = Integer.parseInt(reader.readLine());
A=new int[width*height];
B=new int[width*height];
int index = 0;
String thisLine;
while ((thisLine = reader.readLine()) != null) {
if (thisLine.trim().equals("")) {
break;
} else {
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
A[index] = Integer.parseInt(number);
index++;
}
}
}
index = 0;
while ((thisLine = reader.readLine()) != null) {
if (thisLine.trim().equals("")) {
break;
} else {
String[] lineArray = thisLine.split("\t");
for (String number : lineArray) {
B[index] = Integer.parseInt(number);
index++;
}
}
}
int[] result = matMult(A,B);
System.out.println(result[2]);
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static int[] matMult(int[] A, int[] B) {
int[] C = new int[height*width];
int n = height;
for (int i = 0; i < n; i++) {
for (int k = 0; k < n; k++) {
for (int j = 0; j < n; j++) {
C[width*i+j]+=A[width*i+k] * B[width*k+j];
}
}
}
return C;
}
}
$ time ./IOonly.exe < ../Testing/2000.in
7
944
real 0m8.158s
user 0m0.000s
sys 0m0.046s
$ time java IOOnly < ../Testing/2000.in
7
944
real 0m1.461s
user 0m0.000s
sys 0m0.047s