java - 如何加速这段代码?迭代矩阵的行和列的微积分

标签 java performance trigonometry jama

我有一段代码,它通过迭代矩阵的行和列来执行计算。执行的微积分是余弦距离测量,代码是我在互联网上找到的(现在无法检索链接)。

可以有 10,000 行和列。该矩阵是对称的,所以我只需要迭代它的一半。值是 float 的。

问题:速度非常慢(看起来需要 3 到 6 个小时)。谁能指出我的改进之处吗?谢谢!

代码注释:它使用抽象类来提高灵 active :这样,在单独的类中定义的余弦计算可以很容易地被另一个类替换。

代码:

import Jama.Matrix;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.ExecutionException;

public abstract class AbstractSimilarity {

    HashSet<Triple<Double, Integer, Integer>> set = new HashSet();
    public ArrayList<Thread> listThreads = new ArrayList();

    public void transform(Matrix matrixToBeTransformed) throws InterruptedException, 
ExecutionException {

        int numDocs = termDocumentMatrix.getColumnDimension();

        Main.similarityMatrix = new Matrix(numDocs, numDocs);

        System.out.println("size of the matrix: " + numDocs + "x " + numDocs);

        //1. iteration through all rows of the matrixToBeTransformed
        for (int i = numDocs - 1; i >0 ; i--) {
            System.out.println("matrix treatment... " + ((float) i / (float) numDocs * 100) + "%");

            //2. isolates the row i of this matrixToBeTransformed
            Matrix sourceDocMatrix = matrixToBeTransformed.getMatrix(
                    0, matrixToBeTransformed.getRowDimension() - 1, i, i);



            // 3. Iterates through all columns of the matrixToBeTransformed
//            for (int j = 0; j < numDocs; j++) {
//                if (j < i) {
//
//                    //4. isolates the column j of this matrixToBeTransformed
//                    Matrix targetDocMatrix = matrixToBeTransformed.getMatrix(
//                            0, matrixToBeTransformed.getRowDimension() - 1, j, j);


                    //5. computes the similarity between this given row and this given column and writes it in a resultMatrix
//                    Main.resultMatrix.set(i, j, computeSimilarity(sourceDocMatrix, targetDocMatrix));
//                } else {
//                    Main.resultMatrix.set(i, j, 0);

//                }
//
//            }
        }

定义要完成的计算的类:

import Jama.Matrix;

public class CosineSimilarity extends AbstractSimilarity{

  @Override
  protected double computeSimilarity(Matrix sourceDoc, Matrix targetDoc) {
    double dotProduct = sourceDoc.arrayTimes(targetDoc).norm1();
    double eucledianDist = sourceDoc.normF() * targetDoc.normF();
    return dotProduct / eucledianDist;
  }

}

最佳答案

您似乎正在处理 n^3 算法。 n^2 因为你正在填充一个(一半)矩阵。再次乘以 n 次,因为填充每个元素的方法(点积/fnorm)需要时间 n。好消息是,由于计算不相互依赖,因此您可以使用多线程来加快计算速度。

public class DoCalc extends Thread
{
  public Matrix localM;
  int startRow;
  int endRow;
  public DoCalc(Matrix mArg, int startArg, int endArg)
  {
    localM=mArg;
    startRow=startArg;
    endRow=endArg;
  }

  public void doCalc()
  {
    //Pseudo-code
    for each row from startRow to endRow
      for each column 0 to size-1
        result[i][j] = similarityCalculation
  }
  public void run()
  {
    doCalc();
  }
}

public void transform(Matrix toBeTransformed)
{
  int numDocs = termDocumentMatrix.getColumnDimension();

  Main.similarityMatrix = new Matrix(numDocs, numDocs);
  Vector<DoCalc> running = new Vector<DoCalc>();
  int blockSize = 10;
  for (int x = 0; x < numDocs-1;x+=blockSize)
  {
    DoCalc tempThread = new DoCalc(toBeTransformed,x,(x+blockSize>numDocs-1)?numDocs-1:x+blockSize);
    tempThread.start();
    running.add(tempThread);
  }

  for (DoCalc dc : running)
    dc.join();

}

重要说明:

这是一个非常幼稚的实现。如果您尝试使用您大小的数组运行它,它将产生 1000 个线程。您可以调整 blockSize 或研究线程池。

最多这会给你带来数倍的速度提升,4 倍等。如果你想要数量级的增益,你将需要正确地分析和/或将你的算法更改为更有效的算法。考虑到您要执行的任务(在矩阵中的每个元素上运行相对昂贵的任务),后者可能是不可能的。

编辑:如果您受 CPU 限制并且拥有一个核心相对空闲的多核 CPU,多线程只会显着提高速度。

关于java - 如何加速这段代码?迭代矩阵的行和列的微积分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9535691/

相关文章:

java - Struts2中某些Action的方法验证

java - 如何在jsp或servlet中将 "http headers"从一台主机转发到另一台主机?

javascript - Web Workers 会对 ionic 应用程序有益吗?

C++ 创建绘制斜边的函数 - 三角函数

Java无法正确计算点到线的距离

java - 如何找到已弃用方法的替代品?

java - Minecraft - 漂浮元素消失了这个代码?

php - CSS 预处理器还是 PHP?

linux - vm.dirty_ratio 和 vm.dirty_background_ratio 之间的区别?

javascript - 求反正切?