public static void matrixMult(MatrixBlock m1,MatrixBlock m2,MatrixBlock ret,int k) throws DMLRuntimeException {
  if (m1.isEmptyBlock(false) || m2.isEmptyBlock(false)) {
    ret.examSparsity();
    return;
  }
  if (m1.rlen == 1 && (8L * m2.clen * k > MEM_OVERHEAD_THRESHOLD || !LOW_LEVEL_OPTIMIZATION || m2.clen == 1 || m1.isUltraSparse() || m2.isUltraSparse()) || 2L * m1.rlen * m1.clen* m2.clen < PAR_MINFLOP_THRESHOLD) {
    matrixMult(m1,m2,ret);
    return;
  }
  boolean tm2=checkPrepMatrixMultRightInput(m1,m2);
  m2=prepMatrixMultRightInput(m1,m2);
  ret.sparse=(m1.isUltraSparse() || m2.isUltraSparse());
  if (!ret.sparse)   ret.allocateDenseBlock();
 else   ret.allocateSparseRowsBlock();
  if (!ret.isThreadSafe()) {
    matrixMult(m1,m2,ret);
    return;
  }
  boolean pm2r=checkParMatrixMultRightInputRows(m1,m2,k);
  boolean pm2c=checkParMatrixMultRightInputCols(m1,m2,k,pm2r);
  int num=pm2r ? m2.rlen : pm2c ? m2.clen : m1.rlen;
  try {
    ExecutorService pool=Executors.newFixedThreadPool(k);
    ArrayList<MatrixMultTask> tasks=new ArrayList<MatrixMultTask>();
    int nk=(pm2r || pm2c) ? k : UtilFunctions.roundToNext(Math.min(8 * k,num / 32),k);
    ArrayList<Integer> blklens=getBalancedBlockSizes(num,nk);
    for (int i=0, lb=0; i < blklens.size(); lb+=blklens.get(i), i++)     tasks.add(new MatrixMultTask(m1,m2,ret,tm2,pm2r,pm2c,lb,lb + blklens.get(i)));
    List<Future<Object>> taskret=pool.invokeAll(tasks);
    pool.shutdown();
    ret.nonZeros=0;
    for (    Future<Object> task : taskret) {
      if (pm2r)       vectAdd((double[])task.get(),ret.denseBlock,0,0,ret.rlen * ret.clen);
 else       ret.nonZeros+=(Long)task.get();
    }
    if (pm2r)     ret.recomputeNonZeros();
  }
 catch (  Exception ex) {
    throw new DMLRuntimeException(ex);
  }
  ret.examSparsity();
}

public static void matrixMult ( MatrixBlock m1 , MatrixBlock m2 , MatrixBlock ret , int k ) throws DMLRuntimeException { if ( m1 . isEmptyBlock ( false ) || m2 . isEmptyBlock ( false ) ) { ret . examSparsity ( ) ; return ; } if ( m1 . rlen == 1 && ( 8L * m2 . clen * k > MEM_OVERHEAD_THRESHOLD || ! LOW_LEVEL_OPTIMIZATION || m2 . clen == 1 || m1 . isUltraSparse ( ) || m2 . isUltraSparse ( ) ) || 2L * m1 . rlen * m1 . clen * m2 . clen < PAR_MINFLOP_THRESHOLD ) { matrixMult ( m1 , m2 , ret ) ; return ; } boolean tm2 = checkPrepMatrixMultRightInput ( m1 , m2 ) ; m2 = prepMatrixMultRightInput ( m1 , m2 ) ; ret . sparse = ( m1 . isUltraSparse ( ) || m2 . isUltraSparse ( ) ) ; if ( ! ret . sparse ) ret . allocateDenseBlock ( ) ; else ret . allocateSparseRowsBlock ( ) ; if ( ! ret . isThreadSafe ( ) ) { matrixMult ( m1 , m2 , ret ) ; return ; } boolean pm2r = checkParMatrixMultRightInputRows ( m1 , m2 , k ) ; boolean pm2c = checkParMatrixMultRightInputCols ( m1 , m2 , k , pm2r ) ; int num = pm2r ? m2 . rlen : pm2c ? m2 . clen : m1 . rlen ; try { ExecutorService pool = Executors . newFixedThreadPool ( k ) ; ArrayList < MatrixMultTask > tasks = new ArrayList < MatrixMultTask > ( ) ; int nk = ( pm2r || pm2c ) ? k : UtilFunctions . roundToNext ( Math . min ( 8 * k , num / 32 ) , k ) ; ArrayList < Integer > blklens = getBalancedBlockSizes ( num , nk ) ; for ( int i = 0 , lb = 0 ; i < blklens . size ( ) ; lb += blklens . get ( i ) , i ++ ) tasks . add ( new MatrixMultTask ( m1 , m2 , ret , tm2 , pm2r , pm2c , lb , lb + blklens . get ( i ) ) ) ; List < Future < Object > > taskret = pool . invokeAll ( tasks ) ; pool . shutdown ( ) ; ret . nonZeros = 0 ; for ( Future < Object > task : taskret ) { if ( pm2r ) vectAdd ( ( double [ ] ) task . get ( ) , ret . denseBlock , 0 , 0 , ret . rlen * ret . clen ) ; else ret . nonZeros += ( Long ) task . get ( ) ; } if ( pm2r ) ret . recomputeNonZeros ( ) ; } catch ( Exception ex ) { throw new DMLRuntimeException ( ex ) ; } ret . examSparsity ( ) ; }
performs a multi - threaded matrix multiplication and stores the result in the output matrix . the parameter k ( k > = 1 ) determines the max parallelism k ' with k ' = min ( k , vcores , m1 . rlen ) .
