/*@ VecMTDotBegin - Starts a split phase transpose multiple dot product computation. Input Parameters: + x - the first vector . nv - number of vectors . y - array of vectors - result - where the result will go (can be PETSC_NULL) Level: advanced Notes: Each call to VecMTDotBegin() should be paired with a call to VecMTDotEnd(). .seealso: VecMTDotEnd(), VecNormBegin(), VecNormEnd(), VecNorm(), VecDot(), VecMDot(), VecDotBegin(), VecDotEnd(), VecMDotBegin(), VecMDotEnd(), PetscCommSplitReductionBegin() @*/ PetscErrorCode VecMTDotBegin(Vec x,PetscInt nv,const Vec y[],PetscScalar result[]) { PetscErrorCode ierr; PetscSplitReduction *sr; MPI_Comm comm; int i; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); if (sr->state != STATE_BEGIN) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Called before all VecxxxEnd() called"); for (i=0;i<nv;i++) { if (sr->numopsbegin+i >= sr->maxops) { ierr = PetscSplitReductionExtend(sr);CHKERRQ(ierr); } sr->reducetype[sr->numopsbegin+i] = REDUCE_SUM; sr->invecs[sr->numopsbegin+i] = (void*)x; } if (!x->ops->mtdot_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Vector does not suppport local mdots"); ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); ierr = (*x->ops->mdot_local)(x,nv,y,sr->lvalues+sr->numopsbegin);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); sr->numopsbegin += nv; PetscFunctionReturn(0); }
/*@ VecMDotEnd - Ends a split phase multiple dot product computation. Input Parameters: + x - the first vector (can be PETSC_NULL) . nv - number of vectors - y - array of vectors (can be PETSC_NULL) Output Parameters: . result - where the result will go Level: advanced Notes: Each call to VecMDotBegin() should be paired with a call to VecMDotEnd(). .seealso: VecMDotBegin(), VecNormBegin(), VecNormEnd(), VecNorm(), VecDot(), VecMDot(), VecTDotBegin(),VecTDotEnd(), VecMTDotBegin(), VecMTDotEnd(), PetscCommSplitReductionBegin() @*/ PetscErrorCode VecMDotEnd(Vec x,PetscInt nv,const Vec y[],PetscScalar result[]) { PetscErrorCode ierr; PetscSplitReduction *sr; MPI_Comm comm; int i; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); ierr = PetscSplitReductionEnd(sr);CHKERRQ(ierr); if (sr->numopsend >= sr->numopsbegin) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecxxxEnd() more times then VecxxxBegin()"); if (x && (void*) x != sr->invecs[sr->numopsend]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecxxxEnd() in a different order or with a different vector than VecxxxBegin()"); if (sr->reducetype[sr->numopsend] != REDUCE_SUM) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecDotEnd() on a reduction started with VecNormBegin()"); for (i=0;i<nv;i++) { result[i] = sr->gvalues[sr->numopsend++]; } /* We are finished getting all the results so reset to no outstanding requests */ if (sr->numopsend == sr->numopsbegin) { sr->state = STATE_BEGIN; sr->numopsend = 0; sr->numopsbegin = 0; } PetscFunctionReturn(0); }
/*@ VecNormEnd - Ends a split phase norm computation. Input Parameters: + x - the first vector (can be PETSC_NULL) . ntype - norm type, one of NORM_1, NORM_2, NORM_MAX, NORM_1_AND_2 - result - where the result will go Level: advanced Notes: Each call to VecNormBegin() should be paired with a call to VecNormEnd(). .seealso: VecNormBegin(), VecNorm(), VecDot(), VecMDot(), VecDotBegin(), VecDotEnd(), PetscCommSplitReductionBegin() @*/ PetscErrorCode VecNormEnd(Vec x,NormType ntype,PetscReal *result) { PetscErrorCode ierr; PetscSplitReduction *sr; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); ierr = PetscSplitReductionEnd(sr);CHKERRQ(ierr); if (sr->numopsend >= sr->numopsbegin) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecxxxEnd() more times then VecxxxBegin()"); if (x && (void*)x != sr->invecs[sr->numopsend]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecxxxEnd() in a different order or with a different vector than VecxxxBegin()"); if (sr->reducetype[sr->numopsend] != REDUCE_MAX && ntype == NORM_MAX) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Called VecNormEnd(,NORM_MAX,) on a reduction started with VecDotBegin() or NORM_1 or NORM_2"); result[0] = PetscRealPart(sr->gvalues[sr->numopsend++]); if (ntype == NORM_2) { result[0] = PetscSqrtReal(result[0]); } else if (ntype == NORM_1_AND_2) { result[1] = PetscRealPart(sr->gvalues[sr->numopsend++]); result[1] = PetscSqrtReal(result[1]); } if (ntype!=NORM_1_AND_2) { ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[ntype],result[0]);CHKERRQ(ierr); } if (sr->numopsend == sr->numopsbegin) { sr->state = STATE_BEGIN; sr->numopsend = 0; sr->numopsbegin = 0; } PetscFunctionReturn(0); }
/*@ VecNormBegin - Starts a split phase norm computation. Input Parameters: + x - the first vector . ntype - norm type, one of NORM_1, NORM_2, NORM_MAX, NORM_1_AND_2 - result - where the result will go (can be PETSC_NULL) Level: advanced Notes: Each call to VecNormBegin() should be paired with a call to VecNormEnd(). .seealso: VecNormEnd(), VecNorm(), VecDot(), VecMDot(), VecDotBegin(), VecDotEnd(), PetscCommSplitReductionBegin() @*/ PetscErrorCode VecNormBegin(Vec x,NormType ntype,PetscReal *result) { PetscErrorCode ierr; PetscSplitReduction *sr; PetscReal lresult[2]; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); if (sr->state != STATE_BEGIN) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Called before all VecxxxEnd() called"); if (sr->numopsbegin >= sr->maxops || (sr->numopsbegin == sr->maxops-1 && ntype == NORM_1_AND_2)) { ierr = PetscSplitReductionExtend(sr);CHKERRQ(ierr); } sr->invecs[sr->numopsbegin] = (void*)x; if (!x->ops->norm_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Vector does not support local norms"); ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); ierr = (*x->ops->norm_local)(x,ntype,lresult);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); if (ntype == NORM_2) lresult[0] = lresult[0]*lresult[0]; if (ntype == NORM_1_AND_2) lresult[1] = lresult[1]*lresult[1]; if (ntype == NORM_MAX) sr->reducetype[sr->numopsbegin] = REDUCE_MAX; else sr->reducetype[sr->numopsbegin] = REDUCE_SUM; sr->lvalues[sr->numopsbegin++] = lresult[0]; if (ntype == NORM_1_AND_2) { sr->reducetype[sr->numopsbegin] = REDUCE_SUM; sr->lvalues[sr->numopsbegin++] = lresult[1]; } PetscFunctionReturn(0); }
/*@ PetscCommSplitReductionBegin - Begin an asynchronous split-mode reduction Collective but not synchronizing Input Arguments: comm - communicator on which split reduction has been queued Level: advanced Note: Calling this function is optional when using split-mode reduction. On supporting hardware, calling this after all VecXxxBegin() allows the reduction to make asynchronous progress before the result is needed (in VecXxxEnd()). .seealso: VecNormBegin(), VecNormEnd(), VecDotBegin(), VecDotEnd(), VecTDotBegin(), VecTDotEnd(), VecMDotBegin(), VecMDotEnd(), VecMTDotBegin(), VecMTDotEnd() @*/ PetscErrorCode PetscCommSplitReductionBegin(MPI_Comm comm) { PetscErrorCode ierr; PetscSplitReduction *sr; PetscFunctionBegin; ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); if (sr->numopsend > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Cannot call this after VecxxxEnd() has been called"); if (sr->async) { /* Bad reuse, setup code copied from PetscSplitReductionApply(). */ PetscInt i,numops = sr->numopsbegin,*reducetype = sr->reducetype; PetscScalar *lvalues = sr->lvalues,*gvalues = sr->gvalues; PetscInt sum_flg = 0,max_flg = 0, min_flg = 0; MPI_Comm comm = sr->comm; PetscMPIInt size,cmul = sizeof(PetscScalar)/sizeof(PetscReal);; ierr = PetscLogEventBegin(VEC_ReduceBegin,0,0,0,0);CHKERRQ(ierr); ierr = MPI_Comm_size(sr->comm,&size);CHKERRQ(ierr); if (size == 1) { ierr = PetscMemcpy(gvalues,lvalues,numops*sizeof(PetscScalar));CHKERRQ(ierr); } else { /* determine if all reductions are sum, max, or min */ for (i=0; i<numops; i++) { if (reducetype[i] == REDUCE_MAX) max_flg = 1; else if (reducetype[i] == REDUCE_SUM) sum_flg = 1; else if (reducetype[i] == REDUCE_MIN) min_flg = 1; else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in PetscSplitReduction() data structure, probably memory corruption"); } if (sum_flg + max_flg + min_flg > 1) { /* after all the entires in lvalues we store the reducetype flags to indicate to the reduction operations what are sums and what are max */ for (i=0; i<numops; i++) lvalues[numops+i] = reducetype[i]; ierr = MPIPetsc_Iallreduce(lvalues,gvalues,2*numops,MPIU_SCALAR,PetscSplitReduction_Op,comm,&sr->request);CHKERRQ(ierr); } else if (max_flg) { /* Compute max of real and imag parts separately, presumably only the real part is used */ ierr = MPIPetsc_Iallreduce((PetscReal*)lvalues,(PetscReal*)gvalues,cmul*numops,MPIU_REAL,MPIU_MAX,comm,&sr->request);CHKERRQ(ierr); } else if (min_flg) { ierr = MPIPetsc_Iallreduce((PetscReal*)lvalues,(PetscReal*)gvalues,cmul*numops,MPIU_REAL,MPIU_MIN,comm,&sr->request);CHKERRQ(ierr); } else { ierr = MPIPetsc_Iallreduce(lvalues,gvalues,numops,MPIU_SCALAR,MPIU_SUM,comm,&sr->request);CHKERRQ(ierr); } } sr->state = STATE_PENDING; sr->numopsend = 0; ierr = PetscLogEventEnd(VEC_ReduceBegin,0,0,0,0);CHKERRQ(ierr); } else { ierr = PetscSplitReductionApply(sr);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ VecTDotBegin - Starts a split phase transpose dot product computation. Input Parameters: + x - the first vector . y - the second vector - result - where the result will go (can be PETSC_NULL) Level: advanced Notes: Each call to VecTDotBegin() should be paired with a call to VecTDotEnd(). .seealso: VecTDotEnd(), VecNormBegin(), VecNormEnd(), VecNorm(), VecDot(), VecMDot(), VecDotBegin(), VecDotEnd(), PetscCommSplitReductionBegin() @*/ PetscErrorCode VecTDotBegin(Vec x,Vec y,PetscScalar *result) { PetscErrorCode ierr; PetscSplitReduction *sr; MPI_Comm comm; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); ierr = PetscSplitReductionGet(comm,&sr);CHKERRQ(ierr); if (sr->state != STATE_BEGIN) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Called before all VecxxxEnd() called"); if (sr->numopsbegin >= sr->maxops) { ierr = PetscSplitReductionExtend(sr);CHKERRQ(ierr); } sr->reducetype[sr->numopsbegin] = REDUCE_SUM; sr->invecs[sr->numopsbegin] = (void*)x; if (!x->ops->tdot_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Vector does not suppport local dots"); ierr = PetscLogEventBegin(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); ierr = (*x->ops->dot_local)(x,y,sr->lvalues+sr->numopsbegin++);CHKERRQ(ierr); ierr = PetscLogEventEnd(VEC_ReduceArithmetic,0,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }