/// <summary> /// see <see cref="IMonkeyImplicitPrecond.CreateTempObjects"/> /// </summary> public override void CreateTempObjects(VectorBase x, VectorBase b, MatrixBase mtx, Device dev) { if (!x.IsLocked) { throw new ArgumentException("x must be locked.", "x"); } if (!b.IsLocked) { throw new ArgumentException("b must be locked.", "b"); } if (!mtx.IsLocked) { throw new ArgumentException("mtx must be locked.", "mtx"); } m_Matrix = mtx; m_PcInput = b; m_PcOutput = x; // create objects // ============== _xComm = x.CreateCommVector(mtx); tmp = m_Device.CreateVector(m_PcOutput.Part); // lock objects // ============ tmp.Lock(); m_InvDiag.Lock(); }
/// <summary> /// This function creates the needed temporary objects according to the given parameters /// </summary> /// <param name="pc_output">The output vector</param> /// <param name="pc_input">The input vector</param> /// <param name="mtx">The matrix that is to be multiplied</param> /// <param name="dev"></param> public override void CreateTempObjects(VectorBase pc_output, VectorBase pc_input, MatrixBase mtx, Device dev) { if (!pc_output.IsLocked) { throw new ArgumentException("pc_output must be locked.", "pc_output"); } if (!pc_input.IsLocked) { throw new ArgumentException("pc_input must be locked.", "pc_input"); } if (!mtx.IsLocked) { throw new ArgumentException("mtx must be locked.", "mtx"); } mPcInput = pc_input; mPcOutput = pc_output; m_matrix = mtx; //the temporary objects yOld = m_Device.CreateVector(mPcInput.Part); yNew = m_Device.CreateVector(mPcInput.Part); _yComm = yOld.CreateCommVector(m_matrix); //lock the temporary objects: yOld.Lock(); yNew.Lock(); }
/// <summary> /// performs <paramref name="acc"/> = <paramref name="acc"/>*<paramref name="beta"/> + <paramref name="alpha"/>*this*<paramref name="a"/>; /// </summary> /// <typeparam name="VectorType1"></typeparam> /// <typeparam name="VectorType2"></typeparam> /// <param name="alpha"></param> /// <param name="a"></param> /// <param name="beta"></param> /// <param name="acc"></param> /// <remarks> /// works only in unlocked matrix state (see <see cref="LockAbleObject.Lock"/>, <see cref="LockAbleObject.Unlock"/>); /// </remarks> virtual public void SpMV <VectorType1, VectorType2>(double alpha, VectorType1 a, double beta, VectorType2 acc) where VectorType1 : IList <double> where VectorType2 : IList <double> { if (acc.Count < this.RowPartitioning.LocalLength) { throw new ArgumentException("array is too short - must be as least as big as the local length of the row partition.", "acc"); } if (a.Count < this.ColPartition.LocalLength) { throw new ArgumentException("array is too short - must be as least as big as the local length of the column partition.", "a"); } if (object.ReferenceEquals(a, acc)) { throw new ArgumentException("in-place computation is not supported.", "a,acc"); } // create vector objects bool dummy; VectorBase _a = CreateVec(a, this.ColPartition, out dummy); using (VectorBase.CommVector _a_comm = _a.CreateCommVector(this)) { bool notWriteBackReq; VectorBase _acc = CreateVec(acc, this.RowPartitioning, out notWriteBackReq); // lock objects this.Lock(); _a.Lock(); _acc.Lock(); // check args if (!_a.Part.Equals(this.ColPartition)) { throw new ArgumentException("mismatch between column partition and partition of a.", "a"); } if (!_acc.Part.Equals(this.RowPartitioning)) { throw new ArgumentException("mismatch between row partition and partition of acc.", "acc"); } // real work: SpMV_Expert(alpha, _a_comm, beta, _acc); // unlock _a.Unlock(); _acc.Unlock(); this.Unlock(); // copy back result (if required) if (!notWriteBackReq) { _acc.GetValues(acc, 0, 0, this.RowPartitioning.LocalLength); } } }
/// <summary> /// executes the Jacobi iteration /// </summary> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { // create objects // ============== VectorBase.CommVector _xComm = x.CreateCommVector(m_Matrix); VectorBase tmp = Device.CreateVector(x.Part); VectorBase InvDiag = CreateInvDiag(); // lock objects // ============ x.Lock(); m_Matrix.Lock(); rhs.Lock(); tmp.Lock(); InvDiag.Lock(); // iterate // ======= stats.Converged = false; stats.NoOfIterations = 0; double residualNorm = double.MaxValue; double r_0 = double.NaN; while (true) { // loop termination // ================ if (stats.NoOfIterations >= m_MinIterations) // do at least the minimum number of iterations { if (residualNorm <= m_Tolerance) { // success stats.Converged = true; break; } if (stats.NoOfIterations >= m_MaxIterations) { // terminate break; } } // Jacobi iteration // ================ m_Matrix.SpMV_Expert(-1.0, _xComm, 0.0, tmp); // tmp = -M*x tmp.Acc(1.0, rhs); // tmp = -M*x + rhs if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } double r = Math.Sqrt(tmp.TwoNormSquare()); if (stats.NoOfIterations == 0) { r_0 = r; } if (m_ConvergenceType == ConvergenceTypes.Absolute) { residualNorm = r; } else { residualNorm = r / r_0; } //Console.WriteLine("JACOBI: " + residualNorm); if (m_UnderRelaxationFactor != 1.0) { tmp.Scale(m_UnderRelaxationFactor); } tmp.MultiplyElementWise(InvDiag); x.Acc(1.0, tmp); stats.NoOfIterations++; } // unlock // ====== x.Unlock(); m_Matrix.Unlock(); rhs.Unlock(); InvDiag.Unlock(); }
//[DllImport("Kernel32.dll")] //static extern bool QueryPerformanceCounter(out long lpPerformanceCount); /// <summary> /// implementation of the CG algorithm /// </summary> /// <param name="x"></param> /// <param name="rhs"></param> /// <param name="stats"></param> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { VectorBase P = Device.CreateVector(x.Part); VectorBase.CommVector commP = P.CreateCommVector(m_Matrix); VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals VectorBase V = Device.CreateVector(x.Part); // lock objects // ============ x.Lock(); P.Lock(); R.Lock(); V.Lock(); m_Matrix.Lock(); // compute P0, R0 // ============== // we only need to multiply x once by the Matrix, so we don't want to create // a seperate VectorBase.CommVector - object for x; // Instead, we're temporatily exchangeing the roles of x and P; P.Swap(x); x.CopyFrom(rhs); // x = rhs m_Matrix.SpMV_Expert(-1.0, commP, 1.0, x); // x = rhs - M*x P.Swap(x); R.CopyFrom(P); double alpha = R.TwoNormSquare(); double alpha_0 = alpha; double ResNorm; if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else if (m_ConvergenceType == ConvergenceTypes.Relative) { ResNorm = 1.0; } else { throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString()); } //long total = 0; //long gemv = 0; //long rest = 0; //long st, en; // iterate // ======= stats.Converged = false; stats.NoOfIterations = 1; // one iteration has already been performed (P0, R0) for (int n = m_MaxIterations - 2; n >= 0; n--) { if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations) { stats.Converged = true; break; } if (Math.Abs(alpha) <= double.Epsilon) { // numerical breakdown break; } m_Matrix.SpMV_Expert(1.0, commP, 0, V); double lambda = alpha / V.InnerProd(P); x.Acc(lambda, P); R.Acc(-lambda, V); double alpha_neu = R.TwoNormSquare(); // compute residual norm if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else { ResNorm = Math.Sqrt(alpha / alpha_0); } P.Scale(alpha_neu / alpha); P.Acc(1.0, R); alpha = alpha_neu; stats.NoOfIterations++; //QueryPerformanceCounter(out st); //rest += (st - en); } //Console.WriteLine("CG: R" + stats.NoOfIterations + " = " + ResNorm); // unlock objects // ============== x.Unlock(); P.Unlock(); R.Unlock(); V.Unlock(); m_Matrix.Unlock(); commP.Dispose(); P.Dispose(); V.Dispose(); }
/// <summary> /// implementation of the CG algorithm /// </summary> /// <param name="x"></param> /// <param name="rhs"></param> /// <param name="stats"></param> protected override void CallSolver(VectorBase x, VectorBase rhs, ref SolverResult stats) { VectorBase P = Device.CreateVector(x.Part); VectorBase.CommVector commP = P.CreateCommVector(m_Matrix); VectorBase R = rhs; // rhs is only needed once, so we can use it to store residuals VectorBase V = Device.CreateVector(x.Part); VectorBase Z = Device.CreateVector(x.Part); // lock objects // ============ x.Lock(); P.Lock(); R.Lock(); V.Lock(); Z.Lock(); m_Matrix.Lock(); // configure Precond // ================= if (m_NestedPrecond != null) { m_NestedPrecond.CreateTempObjects(Z, R, m_Matrix, this.Device); } // compute P0, R0 // ============== P.Swap(x); m_Matrix.SpMV_Expert(-1.0, commP, 1.0, R); P.Swap(x); if (m_NestedPrecond != null) { m_NestedPrecond.DoPrecond(); P.CopyFrom(Z); } else { P.CopyFrom(R); } double alpha = R.InnerProd(P); double alpha_0 = alpha; double ResNorm; if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else if (m_ConvergenceType == ConvergenceTypes.Relative) { ResNorm = 1.0; } else { throw new NotImplementedException("unknown convergence type: " + m_ConvergenceType.ToString()); } //long total = 0; //long gemv = 0; //long rest = 0; //long st, en; // iterate // ======= stats.Converged = false; stats.NoOfIterations = 1; // one iteration has allready been performed (P0, R0) for (int n = m_MaxIterations - 2; n >= 0; n--) { if (ResNorm <= m_Tolerance && stats.NoOfIterations >= base.m_MinIterations) { stats.Converged = true; break; } if (Math.Abs(alpha) <= double.Epsilon) { // numerical breakdown break; } m_Matrix.SpMV_Expert(1.0, commP, 0, V); double lambda = alpha / V.InnerProd(P); x.Acc(lambda, P); R.Acc(-lambda, V); if (m_IterationCallback != null) { // pass approx. sol and residual to callback function x.Unlock(); R.Unlock(); double[] x_approx = new double[x.Part.LocalLength]; x.CopyTo(x_approx, 0); double[] R_curr = new double[R.Part.LocalLength]; R.CopyTo(R_curr, 0); m_IterationCallback(stats.NoOfIterations, x_approx, R_curr); x.Lock(); R.Lock(); } if (m_NestedPrecond != null) { Z.Clear(); m_NestedPrecond.DoPrecond(); } else { Z.CopyFrom(R); } double alpha_neu = R.InnerProd(Z); // compute residual norm if (m_ConvergenceType == ConvergenceTypes.Absolute) { ResNorm = Math.Sqrt(alpha); } else { ResNorm = Math.Sqrt(alpha / alpha_0); } ResNorm = Math.Sqrt(R.TwoNormSquare()); P.Scale(alpha_neu / alpha); P.Acc(1.0, Z); alpha = alpha_neu; stats.NoOfIterations++; } // unlock objects // ============== if (m_NestedPrecond != null) { m_NestedPrecond.ReleaseTempObjects(); } x.Unlock(); P.Unlock(); R.Unlock(); V.Unlock(); m_Matrix.Unlock(); commP.Dispose(); P.Dispose(); }