public static void matrixMultChain(MatrixBlock mX,MatrixBlock mV,MatrixBlock mW,MatrixBlock ret,ChainType ct,int k) throws DMLRuntimeException {
  if (mX.isEmptyBlock(false) || mV.isEmptyBlock(false) || (mW != null && mW.isEmptyBlock(false))) {
    ret.examSparsity();
    return;
  }
  if (8L * mV.rlen * k > MEM_OVERHEAD_THRESHOLD || 4L * mX.rlen * mX.clen < PAR_MINFLOP_THRESHOLD) {
    matrixMultChain(mX,mV,mW,ret,ct);
    return;
  }
  ret.sparse=false;
  ret.allocateDenseBlock();
  try {
    ExecutorService pool=Executors.newFixedThreadPool(k);
    ArrayList<MatrixMultChainTask> tasks=new ArrayList<MatrixMultChainTask>();
    int blklen=(int)(Math.ceil((double)mX.rlen / k));
    blklen+=(blklen % 24 != 0) ? 24 - blklen % 24 : 0;
    for (int i=0; i < k & i * blklen < mX.rlen; i++)     tasks.add(new MatrixMultChainTask(mX,mV,mW,ct,i * blklen,Math.min((i + 1) * blklen,mX.rlen)));
    List<Future<double[]>> taskret=pool.invokeAll(tasks);
    pool.shutdown();
    for (    Future<double[]> task : taskret)     vectAdd(task.get(),ret.denseBlock,0,0,mX.clen);
  }
 catch (  Exception ex) {
    throw new DMLRuntimeException(ex);
  }
  ret.recomputeNonZeros();
  ret.examSparsity();
}

public static void matrixMultChain ( MatrixBlock mX , MatrixBlock mV , MatrixBlock mW , MatrixBlock ret , ChainType ct , int k ) throws DMLRuntimeException { if ( mX . isEmptyBlock ( false ) || mV . isEmptyBlock ( false ) || ( mW != null && mW . isEmptyBlock ( false ) ) ) { ret . examSparsity ( ) ; return ; } if ( 8L * mV . rlen * k > MEM_OVERHEAD_THRESHOLD || 4L * mX . rlen * mX . clen < PAR_MINFLOP_THRESHOLD ) { matrixMultChain ( mX , mV , mW , ret , ct ) ; return ; } ret . sparse = false ; ret . allocateDenseBlock ( ) ; try { ExecutorService pool = Executors . newFixedThreadPool ( k ) ; ArrayList < MatrixMultChainTask > tasks = new ArrayList < MatrixMultChainTask > ( ) ; int blklen = ( int ) ( Math . ceil ( ( double ) mX . rlen / k ) ) ; blklen += ( blklen % 24 != 0 ) ? 24 - blklen % 24 : 0 ; for ( int i = 0 ; i < k & i * blklen < mX . rlen ; i ++ ) tasks . add ( new MatrixMultChainTask ( mX , mV , mW , ct , i * blklen , Math . min ( ( i + 1 ) * blklen , mX . rlen ) ) ) ; List < Future < double [ ] > > taskret = pool . invokeAll ( tasks ) ; pool . shutdown ( ) ; for ( Future < double [ ] > task : taskret ) vectAdd ( task . get ( ) , ret . denseBlock , 0 , 0 , mX . clen ) ; } catch ( Exception ex ) { throw new DMLRuntimeException ( ex ) ; } ret . recomputeNonZeros ( ) ; ret . examSparsity ( ) ; }
performs a parallel matrix multiplication chain operation of type t ( x ) % * % ( x % * % v ) or t ( x ) % * % ( w * ( x % * % v ) ) . the parameter k ( k > = 1 ) determines the max parallelism k ' with k ' = min ( k , vcores , m1 . rlen ) . note : this multi - threaded mmchain operation has additional memory requirements of k * ncol ( x ) * 8bytes for partial aggregation . current max memory : 256kb ; otherwise redirectly to sequential execution .
