gpt4 book ai didi

java - 迭代性能 Java 与 C++

转载 作者:可可西里 更新时间:2023-11-01 16:26:34 25 4
gpt4 key购买 nike

这个问题让我困惑了 3 天。我有一个应用程序需要评估一组元素很少的整数多项式(多个参数)。我已经有一个用 Java 编写的实现,我目前正在移植到 C++。

在测试期间,我注意到 C++ 版本比 Java 变体慢几个数量级。我当然知道 JIT-ing 并且这种情况特别适合这种编译器,但我所看到的与我的预期相去甚远。

下面是示例代码,您需要 boost 来编译 C++ 代码(但只有简单的时间测量才需要这种依赖)。

choeger@daishi ~/uebb % clang++ -O3 -std=c++11 polytest.cpp -lboost_timer -lboost_system
choeger@daishi ~/uebb % ./a.out
0.011694s wall, 0.010000s user + 0.000000s system = 0.010000s CPU (85.5%)
Ideal Result: 1e+07
0.421986s wall, 0.420000s user + 0.000000s system = 0.420000s CPU (99.5%)
Result: 1e+07
choeger@daishi ~/uebb % javac PolyTest.java
choeger@daishi ~/uebb % java PolyTest
evals: 10000000 runtime: 17ms
Ideal Result: 1.0E7
evals: 10000000 runtime: 78ms
Result: 1.0E7

显然,就纯计算能力而言,C++ 版本(使用 clang-3.3 编译)运行速度稍快,但在解释多项式时,Java (openjdk 1.7.0.60) 的表现要好得多。到目前为止,我的猜测是,由于对小(样本 1 元素) vector 的迭代,我的 C++ 代码不是很理想。我假设 JVM 在缓存命中未命中方面做得更好。

有什么方法可以使我的 C++ 版本性能更好?我只是没有看到其他原因吗?附带说明:有没有办法测量 C++ 和 Java 进程的缓存一致性?

C++ 代码如下所示:

#include <boost/timer/timer.hpp>

#include <iostream>
#include <vector>

using namespace std;

struct Product {
int factor;
vector<int> fields;
};


class SumOfProducts {
public:
vector<Product> sum;

/**
* evaluate the polynomial with arguments separated by width
*/
inline double eval(const double* arg, const int width) const {
double res = 0.0;
for (Product p : sum) {
double prod = p.factor;
for (int f : p.fields) {
prod *= arg[f*width];
}
res += prod;
}
return res;
};
};


double idealBenchmark(const double* arg, const int width) {
boost::timer::auto_cpu_timer t;
double res = 0.0;
// run 10M evaluations
for (long l = 0; l < 10000000; l++) {
res = res + arg[width] * arg[width];
}
return res;
}

double benchmark(const double* arg, const SumOfProducts& poly) {
boost::timer::auto_cpu_timer t;
double res = 0.0;
// run 10M evaluations
for (long l = 0; l < 10000000; l++) {
res = res + poly.eval(arg, 1);
}
return res;
}

int main() {
//simple polynomial: x_1^2
Product p;
p.factor = 1;
p.fields.push_back(1);
p.fields.push_back(1);

SumOfProducts poly;
poly.sum.push_back(p);

double arg[] = { 0, 1 };

double res = idealBenchmark(arg, 1);
cout << "Ideal Result: " << res << endl;

res = benchmark(arg, poly);
cout << "Result: " << res << endl;
}

Java 版本是这样的:

public class PolyTest {

static class Product {
public final int factor;
public final int[] fields;

public Product(int pFactor, int[] pFields) {
factor = pFactor;
fields = pFields;
}
}

static class SumOfProducts {
final Product[] sum;

public SumOfProducts(Product[] pSum) {
sum = pSum;
}

/**
* evaluate the polynomial with arguments separated by width
*/
double eval(final double[] arg, final int width) {
double res = 0.0;
for (Product p : sum) {
double prod = p.factor;
for (int f : p.fields) {
prod *= arg[f*width];
}
res += prod;
}
return res;
}
}

static double idealBenchmark(final double[] arg, final int width) {
final long start = System.currentTimeMillis();
double res = 0.0;
long evals = 0;
// run 10M evaluations
for (long l = 0; l < 10000000; l++) {
evals++;
res = res + arg[width] * arg[width];
}
System.out.println("evals: " + evals + " runtime: " + (System.currentTimeMillis() - start) + "ms");
return res;
}

static double benchmark(final double[] arg, final SumOfProducts poly) {
final long start = System.currentTimeMillis();
double res = 0.0;
long evals = 0;
// run 10M evaluations
for (long l = 0; l < 10000000; l++) {
evals++;
res = res + poly.eval(arg, 1);
}
System.out.println("evals: " + evals + " runtime: " + (System.currentTimeMillis() - start) + "ms");
return res;
}

public static void main(String[] args) {
//simple polynomial: x_1^2
Product p = new Product(1, new int[]{1, 1});

SumOfProducts poly = new SumOfProducts(new Product[]{p});

double arg[] = { 0, 1 };

double res = idealBenchmark(arg, 1);
System.out.println("Ideal Result: " + res);

res = benchmark(arg, poly);
System.out.println("Result: " + res);
}

}

最佳答案

你在这里制作昂贵的拷贝:

for (Product p : sum)

每次复制意味着完全复制 std::vector<int>每个元素的数据成员。改用引用:

for (const Product& p : sum)

请注意,我制作了它们 const ,因为您不需要更改范围的元素。

关于java - 迭代性能 Java 与 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21007029/

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