Real ComplementRatio ( const ElementalMatrix<Real>& sPre, const ElementalMatrix<Real>& zPre ) { DEBUG_CSE ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadProxy<Real,Real,VC,STAR> sProx( sPre, ctrl ), zProx( zPre, ctrl ); auto& s = sProx.GetLocked(); auto& z = zProx.GetLocked(); const Int localHeight = s.LocalHeight(); const Real* sBuf = s.LockedBuffer(); const Real* zBuf = z.LockedBuffer(); Real maxLocProd = 0; for( Int iLoc=0; iLoc<localHeight; ++iLoc ) maxLocProd = Max( sBuf[iLoc]*zBuf[iLoc], maxLocProd ); const Real maxProd = mpi::AllReduce( maxLocProd, mpi::MAX, s.DistComm() ); Real minLocProd = maxProd; for( Int iLoc=0; iLoc<localHeight; ++iLoc ) minLocProd = Min( sBuf[iLoc]*zBuf[iLoc], minLocProd ); const Real minProd = mpi::AllReduce( minLocProd, mpi::MIN, s.DistComm() ); return maxProd/minProd; }
void NesterovTodd ( const ElementalMatrix<Real>& sPre, const ElementalMatrix<Real>& zPre, ElementalMatrix<Real>& wPre ) { DEBUG_CSE ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadProxy<Real,Real,VC,STAR> sProx( sPre, ctrl ), zProx( zPre, ctrl ); DistMatrixWriteProxy<Real,Real,VC,STAR> wProx( wPre, ctrl ); auto& s = sProx.GetLocked(); auto& z = zProx.GetLocked(); auto& w = wProx.Get(); w.Resize( s.Height(), 1 ); const Int localHeight = w.LocalHeight(); const Real* sBuf = s.LockedBuffer(); const Real* zBuf = z.LockedBuffer(); Real* wBuf = w.Buffer(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) wBuf[iLoc] = Sqrt(sBuf[iLoc]/zBuf[iLoc]); }
void PushPairInto ( ElementalMatrix<Real>& sPre, ElementalMatrix<Real>& zPre, const ElementalMatrix<Real>& wPre, const ElementalMatrix<Int>& ordersPre, const ElementalMatrix<Int>& firstIndsPre, Real wMaxNormLimit, Int cutoff ) { DEBUG_ONLY(CSE cse("soc::PushPairInto")) AssertSameGrids( sPre, zPre, wPre, ordersPre, firstIndsPre ); ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadWriteProxy<Real,Real,VC,STAR> sProx( sPre, ctrl ), zProx( zPre, ctrl ); DistMatrixReadProxy<Real,Real,VC,STAR> wProx( wPre, ctrl ); DistMatrixReadProxy<Int,Int,VC,STAR> ordersProx( ordersPre, ctrl ), firstIndsProx( firstIndsPre, ctrl ); auto& s = sProx.Get(); auto& z = zProx.Get(); auto& w = wProx.GetLocked(); auto& orders = ordersProx.GetLocked(); auto& firstInds = firstIndsProx.GetLocked(); DistMatrix<Real,VC,STAR> sLower(s.Grid()), zLower(z.Grid()); soc::LowerNorms( s, sLower, orders, firstInds, cutoff ); soc::LowerNorms( z, zLower, orders, firstInds, cutoff ); const Int localHeight = s.LocalHeight(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const Int i = s.GlobalRow(iLoc); const Real w0 = w.GetLocal(iLoc,0); if( i == firstInds.GetLocal(iLoc,0) && w0 > wMaxNormLimit ) { // TODO: Switch to a non-adhoc modification s.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit ); z.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit ); } } }
Real MaxStep ( const AbstractDistMatrix<Real>& sPre, const AbstractDistMatrix<Real>& dsPre, Real upperBound ) { EL_DEBUG_CSE // TODO(poulson): Decide if more general intermediate distributions should // be supported. DistMatrixReadProxy<Real,Real,MC,MR> sProx( sPre ); auto& s = sProx.GetLocked(); ElementalProxyCtrl control; control.colConstrain = true; control.rowConstrain = true; control.colAlign = s.ColAlign(); control.rowAlign = s.RowAlign(); DistMatrixReadProxy<Real,Real,MC,MR> dsProx( dsPre, control ); auto& ds = dsProx.GetLocked(); const Real* sBuf = s.LockedBuffer(); const Real* dsBuf = ds.LockedBuffer(); Real alpha = upperBound; if( s.IsLocalCol(0) ) { const Int kLocal = s.LocalHeight(); for( Int iLoc=0; iLoc<kLocal; ++iLoc ) { const Real si = sBuf[iLoc]; const Real dsi = dsBuf[iLoc]; if( dsi < Real(0) ) alpha = Min(alpha,-si/dsi); } } return mpi::AllReduce( alpha, mpi::MIN, s.DistComm() ); }
SVDInfo ScaLAPACKHelper ( const AbstractDistMatrix<F>& APre, AbstractDistMatrix<F>& UPre, AbstractDistMatrix<Base<F>>& sPre, AbstractDistMatrix<F>& V, const SVDCtrl<Base<F>>& ctrl ) { DEBUG_CSE AssertScaLAPACKSupport(); SVDInfo info; #ifdef EL_HAVE_SCALAPACK typedef Base<F> Real; DistMatrix<F,MC,MR,BLOCK> A( APre ); DistMatrixWriteProxy<Real,Real,STAR,STAR> sProx(sPre); DistMatrixWriteProxy<F,F,MC,MR,BLOCK> UProx(UPre); auto& s = sProx.Get(); auto& U = UProx.Get(); const int m = A.Height(); const int n = A.Width(); const int k = Min(m,n); auto approach = ctrl.bidiagSVDCtrl.approach; if( approach == THIN_SVD || approach == COMPACT_SVD ) { Zeros( U, m, k ); DistMatrix<F,MC,MR,BLOCK> VH( A.Grid() ); Zeros( VH, k, n ); s.Resize( k, 1 ); auto descA = FillDesc( A ); auto descU = FillDesc( U ); auto descVH = FillDesc( VH ); scalapack::SVD ( m, n, A.Buffer(), descA.data(), s.Buffer(), U.Buffer(), descU.data(), VH.Buffer(), descVH.data() ); const bool compact = ( approach == COMPACT_SVD ); if( compact ) { const Real twoNorm = ( k==0 ? Real(0) : s.Get(0,0) ); const Real thresh = bidiag_svd::APosterioriThreshold ( m, n, twoNorm, ctrl.bidiagSVDCtrl ); Int rank = k; for( Int j=0; j<k; ++j ) { if( s.Get(j,0) <= thresh ) { rank = j; break; } } s.Resize( rank, 1 ); U.Resize( m, rank ); VH.Resize( rank, n ); } Adjoint( VH, V ); } else LogicError ("Only Thin and Compact singular value options currently supported"); #endif return info; }