Java计算速度加倍

发布于 2025-01-01 03:57:01 字数 1123 浏览 1 评论 0原文

我有一段代码需要基于双精度值进行许多计算,这需要太多时间。我可以通过去掉一些小数来加快速度吗?如果我使用格式化程序来解析双精度数,是否会先进行微积分,然后去掉多余的小数,所以什么也得不到?这样做的最好方法是什么?

只是想了解一下:

double avgRatingForPreferredItem = (double) tempAverageRating.get(matrix.get(0).getItemID1())/matrix.size(); 
   double avgRatingForRandomItem = (double) tempAverageRating.get(matrix.get(0).getItemID2())/matrix.size();

double numarator = 0;
   for (MatrixColumn matrixCol : matrix) {
     numarator += ( matrixCol.getRatingForItemID1() - avgRatingForPreferredItem ) * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
   }

   double numitor = 0;
   double numitorStanga = 0;
   double numitorDreapta = 0;
   for (MatrixColumn matrixCol : matrix) {
     numitorStanga += (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem) * (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem);
     numitorDreapta += (matrixCol.getRatingForItemID2() - avgRatingForRandomItem) * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
   }

   numitor = Math.sqrt( numitorStanga * numitorDreapta );

   double corelare = numarator/numitor;

I have a piece of code that needs to do many computations based on double values, which takes too much time. Can I speed this up by dropping some decimals? if I use a formatter to parse the double, won't that do the calculus first and then shed the extra decimals, so nothing would be gained? what's the best way of doing this?

Just something to get an idea:

double avgRatingForPreferredItem = (double) tempAverageRating.get(matrix.get(0).getItemID1())/matrix.size(); 
   double avgRatingForRandomItem = (double) tempAverageRating.get(matrix.get(0).getItemID2())/matrix.size();

double numarator = 0;
   for (MatrixColumn matrixCol : matrix) {
     numarator += ( matrixCol.getRatingForItemID1() - avgRatingForPreferredItem ) * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
   }

   double numitor = 0;
   double numitorStanga = 0;
   double numitorDreapta = 0;
   for (MatrixColumn matrixCol : matrix) {
     numitorStanga += (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem) * (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem);
     numitorDreapta += (matrixCol.getRatingForItemID2() - avgRatingForRandomItem) * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
   }

   numitor = Math.sqrt( numitorStanga * numitorDreapta );

   double corelare = numarator/numitor;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

背叛残局 2025-01-08 03:57:01

我不相信所涉及的实际值会产生任何影响。

至少值得尝试减少此处的计算:

for (MatrixColumn matrixCol : matrix) {
 numitorStanga  += (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem)
                 * (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem);
 numitorDreapta += (matrixCol.getRatingForItemID2() - avgRatingForRandomItem) 
                 * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
}

这取决于 JIT 编译器的智能程度 - 我假设 getRatingforItemID1getRatingforItemID2只是传递属性 - 但您的代码至少看起来像是在进行冗余减法。所以:

for (MatrixColumn matrixCol : matrix) {
  double diff1 = matrixCol.getRatingForItemID1() - avgRatingForPreferredItem;
  double diff2 = matrixCol.getRatingForItemID2() - avgRatingForPreferredItem;
  numitorStanga += diff1 * diff1;
  numitorDreapta += diff2 * diff2;
}

您可以尝试将所有内容更改为float而不是double - 在某些架构上可能会使事情变得更快;对其他人来说可能不会。

不过,您绝对确定您所显示的代码有问题吗?这只是一个 O(N) 算法——需要多长时间,矩阵有多大?

I don't believe the actual values involved can make any difference.

It's worth at least trying to reduce the computations here:

for (MatrixColumn matrixCol : matrix) {
 numitorStanga  += (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem)
                 * (matrixCol.getRatingForItemID1() - avgRatingForPreferredItem);
 numitorDreapta += (matrixCol.getRatingForItemID2() - avgRatingForRandomItem) 
                 * (matrixCol.getRatingForItemID2() - avgRatingForRandomItem);
}

It depends on how smart the JIT compiler is - and I'm assuming getRatingforItemID1 and getRatingforItemID2 are just pass-through properties - but your code at least looks like it's doing redundant subtractions. So:

for (MatrixColumn matrixCol : matrix) {
  double diff1 = matrixCol.getRatingForItemID1() - avgRatingForPreferredItem;
  double diff2 = matrixCol.getRatingForItemID2() - avgRatingForPreferredItem;
  numitorStanga += diff1 * diff1;
  numitorDreapta += diff2 * diff2;
}

You could try changing everything to float instead of double - on some architectures that may make things faster; on others it may well not.

Are you absolutely sure that it's the code you've shown which has the problem, though? It's only an O(N) algorithm - how long is it taking, and how large is the matrix?

白鸥掠海 2025-01-08 03:57:01

无论小数位数如何,浮点计算的速度都是相同的。这是硬件,所以无论如何它每次都会以完整的值运行。另请记住,小数位数无论如何都是无关紧要的,double将数字存储在二进制中,仅截断小数位数就可以创建相同的结果-length 二进制表示。

Floating-point calculations are the same speed regardless of the decimal places. This is hardware, so it operates on the complete value every time anyway. Also keep in mind that the number of decimal places is irrelevant anyway, double stores numbers in binary and just truncating decimal places could well create a same-length binary representation.

爱要勇敢去追 2025-01-08 03:57:01

另一种加快速度的方法是使用数组而不是对象。使用对象的问题是你不知道它们在内存中是如何排列的(根据我的经验,这通常很糟糕,因为 JVM 根本没有对此进行优化)

double avgRatingForPreferredItem = (double) tempAverageRating.get(matrix.get(0).getItemID1()) / matrix.size();
double avgRatingForRandomItem = (double) tempAverageRating.get(matrix.get(0).getItemID2()) / matrix.size();

double[] ratingForItemID1 = matrix.getRatingForItemID1();
double[] ratingForItemID2 = matrix.getRatingForItemID2();
double numarator = 0, numitorStanga = 0, numitorDreapta = 0;
for (int i = 0; i < ratingForItemID1.length; i++) {
    double rating1 = ratingForItemID1[i] - avgRatingForPreferredItem;
    double rating2 = ratingForItemID2[i] - avgRatingForRandomItem;
    numarator += rating1 * rating2;
    numitorStanga += rating1 * rating1;
    numitorDreapta += rating2 * rating2;
}

double numitor = Math.sqrt(numitorStanga * numitorDreapta);
double corelare = numarator / numitor;

在内存中连续访问数据可能比随机访问快 5 倍。

Another way to make this faster is to use arrays instead of objects. The problem with using objects is you have no idea how they are arranged in memory (often badly in my experience as the JVM doesn't optimise for this at all)

double avgRatingForPreferredItem = (double) tempAverageRating.get(matrix.get(0).getItemID1()) / matrix.size();
double avgRatingForRandomItem = (double) tempAverageRating.get(matrix.get(0).getItemID2()) / matrix.size();

double[] ratingForItemID1 = matrix.getRatingForItemID1();
double[] ratingForItemID2 = matrix.getRatingForItemID2();
double numarator = 0, numitorStanga = 0, numitorDreapta = 0;
for (int i = 0; i < ratingForItemID1.length; i++) {
    double rating1 = ratingForItemID1[i] - avgRatingForPreferredItem;
    double rating2 = ratingForItemID2[i] - avgRatingForRandomItem;
    numarator += rating1 * rating2;
    numitorStanga += rating1 * rating1;
    numitorDreapta += rating2 * rating2;
}

double numitor = Math.sqrt(numitorStanga * numitorDreapta);
double corelare = numarator / numitor;

Accessing data continuously in memory can be 5x faster than random access.

神魇的王 2025-01-08 03:57:01

您可以通过将浮点值更改为长值(根据您需要的小数位数进行缩放)来加速算法(取决于所使用的值范围),即 value * 10000为 4 位小数。

如果您选择这样做,则需要记住除法和乘法的比例 (numitorDreapta += (diff2 * diff2) / 10000;),这确实会给您的代码带来一些混乱。

您需要在之前和之后进行转换,但如果您需要使用整数算术而不是浮点进行大量计算,可能会产生您想要的加速。

You might be able to speed up your algorithm (depending on the value range used) by changing your floating point values into long values that are scaled according to the number of decimal places you need, i.e. value * 10000 for 4 decimal places.

If you chose to do this, you will need to keep the scale in mind for division and multiplication (numitorDreapta += (diff2 * diff2) / 10000;) which does add some clutter to your code.

You will need to convert before and after, but if you need to do a lot of calculations using integer arithmetic instead of floating point might yield the speedup you are looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文