On Wed, Feb 15, 2012 at 8:53 PM, Sylvain Barbot <span dir="ltr">&lt;<a href="mailto:sylbar.vainbot@gmail.com">sylbar.vainbot@gmail.com</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Matt,<br>
<br>
You&#39;re right, I&#39;m not worried about the interior points, that why I&#39;m<br>
looking for updating the ghost points only - the interior points<br>
unaffected by the process. Jed seems to indicate that it&#39;s not a<br>
bottle neck.<br>
<br>
Jed,<br>
<br>
Would you recommend a particular step to improve cache performance?<br>
Can you be a bit more specific?<br></blockquote><div><br></div><div>R-B has crappy cache performance since you alternately pull data but ignore</div><div>half of it. Why not just use the GMG in PETSc? Its very flexible, scalable,</div>
<div>and efficient.</div><div><br></div><div>   Matt</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sylvain<br>
<br>
2012/2/15 Matthew Knepley &lt;<a href="mailto:knepley@gmail.com">knepley@gmail.com</a>&gt;:<br>
&gt; On Wed, Feb 15, 2012 at 5:25 PM, Sylvain Barbot &lt;<a href="mailto:sylbar.vainbot@gmail.com">sylbar.vainbot@gmail.com</a>&gt;<br>
<div class="im">&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi All,<br>
&gt;&gt;<br>
&gt;&gt; I&#39;m implementing an elasticity multi-grid solver with Petsc with<br>
&gt;&gt; matrix shells. I am using the Red-Black Gauss-Siedel smoother. In the<br>
&gt;&gt; middle of the Red-Black passes, I need to update the ghost points<br>
&gt;&gt; between processors. To do that effectively, I&#39;d like to update only<br>
&gt;&gt; the ghost points between the different processors, instead of the<br>
&gt;&gt; whole array. The goal is to do the most possible operations in place<br>
&gt;<br>
&gt;<br>
</div>&gt; What does that mean? Updating ghost dofs means taking the value of that<br>
&gt; dof on the process that owns it, and copying it to all the processes which<br>
&gt; hold<br>
&gt; that as a ghost dof. This operation has no meaning for interior points.<br>
&gt;<br>
&gt;     Matt<br>
<div class="im">&gt;<br>
&gt;&gt;<br>
&gt;&gt; in local array lx, and having to update global vector x only once. The<br>
&gt;&gt; working matrix multiply smoothing operation is shown below. I&#39;m using<br>
&gt;&gt; Petsc 3.1. I read about<br>
&gt;&gt;<br>
&gt;&gt; <a href="http://www.mcs.anl.gov/petsc/petsc-3.1/docs/manualpages/Vec/VecGhostUpdateBegin.html" target="_blank">http://www.mcs.anl.gov/petsc/petsc-3.1/docs/manualpages/Vec/VecGhostUpdateBegin.html</a>,<br>
&gt;&gt; but I&#39;m not entirely clear whether this does what I want or not.<br>
&gt;&gt;<br>
&gt;&gt;<br>
</div>&gt;&gt; SUBROUTINE matrixsmooth(A,b,omega,flag,shift,its,level,x,ierr)<br>
&gt;&gt;    USE types<br>
&gt;&gt;    USE heap<br>
&gt;&gt;    USE petscsys<br>
&gt;&gt;    USE petscda<br>
&gt;&gt;    USE petscis<br>
&gt;&gt;    USE petscvec<br>
&gt;&gt;    USE petscmat<br>
&gt;&gt;    USE petscpc<br>
&gt;&gt;    USE petscksp<br>
&gt;&gt;<br>
&gt;&gt;    IMPLICIT NONE<br>
&gt;&gt;<br>
&gt;&gt;    Mat, INTENT(IN) :: A<br>
&gt;&gt;    Vec, INTENT(IN) :: b<br>
&gt;&gt;    Vec, INTENT(INOUT) :: x<br>
&gt;&gt;    PetscReal, INTENT(IN) :: omega,shift<br>
&gt;&gt;    MatSORType, INTENT(IN) :: flag<br>
&gt;&gt;    PetscInt, INTENT(IN) :: its, level ! iterations, multi-grid level<br>
&gt;&gt;    PetscErrorCode, INTENT(OUT) :: ierr<br>
&gt;&gt;<br>
&gt;&gt;    Vec :: lx,lb<br>
&gt;&gt;    PetscInt :: istart,iend<br>
&gt;&gt;    PetscScalar, POINTER :: px(:) ! pointer to solution array<br>
&gt;&gt;    PetscScalar, POINTER :: pb(:) ! pointer to body-force array<br>
&gt;&gt;    INTEGER :: rank,isize,i,k<br>
&gt;&gt;    INTEGER :: sw,off,p<br>
&gt;&gt;    INTEGER :: i2,i3,i2i,i3i, &amp;<br>
&gt;&gt;               i000,i0p0,i00p, &amp;<br>
&gt;&gt;               i0m0,i00m<br>
&gt;&gt;    TYPE(DALOCALINFOF90) :: info<br>
&gt;&gt;<br>
&gt;&gt;    CALL MPI_COMM_RANK(PETSC_COMM_WORLD,rank,ierr)<br>
&gt;&gt;    CALL MPI_COMM_SIZE(PETSC_COMM_WORLD,isize,ierr)<br>
&gt;&gt;<br>
&gt;&gt;    CALL VecGetOwnershipRange(x,istart,iend,ierr)<br>
&gt;&gt;<br>
&gt;&gt;    ! allocate memory for local vector with ghost points<br>
&gt;&gt;    CALL DACreateLocalVector(c%daul(1+level),lx,ierr)<br>
&gt;&gt;    CALL VecDuplicate(lx,lb,ierr)<br>
&gt;&gt;<br>
&gt;&gt;    ! retrieve forcing term b with ghost points<br>
&gt;&gt;    CALL DAGlobalToLocalBegin(c%daul(1+level),b,INSERT_VALUES,lb,ierr)<br>
&gt;&gt;    CALL DAGlobalToLocalEnd(c%daul(1+level),b,INSERT_VALUES,lb,ierr)<br>
&gt;&gt;<br>
&gt;&gt;    ! obtain a pointer to local data<br>
&gt;&gt;    CALL VecGetArrayF90(lx,px,ierr);<br>
&gt;&gt;    CALL VecGetArrayF90(lb,pb,ierr);<br>
&gt;&gt;<br>
&gt;&gt;    ! geometry info about local vector and padding<br>
&gt;&gt;    CALL DAGetLocalInfoF90(c%daul(1+level),info,ierr);<br>
&gt;&gt;<br>
&gt;&gt;    ! retrieve stencil width (ghost-point padding)<br>
&gt;&gt;    CALL DAGetInfo(c%daul(1+level),PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &amp;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,<br>
&gt;&gt; &amp;<br>
&gt;&gt;                   PETSC_NULL_INTEGER,PETSC_NULL_INTEGER, &amp;<br>
&gt;&gt;                   sw,PETSC_NULL_INTEGER, &amp;<br>
&gt;&gt;                   PETSC_NULL_INTEGER,ierr);<br>
&gt;&gt;<br>
&gt;&gt;    ! offset due to node topology<br>
&gt;&gt;    off=MOD(info%xm+info%ym,2)<br>
&gt;&gt;<br>
&gt;&gt;    ! fast smoothing (relaxation) its=number of iteration<br>
&gt;&gt;    DO k=1,its<br>
&gt;&gt;       ! Red-Black Gauss-Siedel scheme<br>
&gt;&gt;       DO p=0,1<br>
&gt;&gt;          ! retrieve initial guess x with ghost points<br>
&gt;&gt;          CALL<br>
&gt;&gt; DAGlobalToLocalBegin(c%daul(1+level),x,INSERT_VALUES,lx,ierr)<br>
&gt;&gt;          CALL DAGlobalToLocalEnd(c%daul(1+level),x,INSERT_VALUES,lx,ierr)<br>
&gt;&gt;          ! smoothing (relaxation)<br>
&gt;&gt;          DO i=istart+p+off,iend-1,info%dof*2<br>
&gt;&gt;             i3=(i-istart)/(info%xm*info%dof)<br>
&gt;&gt;             i2=(i-istart-i3*info%xm*info%dof)/info%dof<br>
&gt;&gt;             i3=i3+i3i    ! i3 in ( 0 .. sx3-1 )<br>
&gt;&gt;             i2=i2+i2i    ! i2 in ( 0 .. sx2-1 )<br>
&gt;&gt;<br>
&gt;&gt;             i000=1+((sw+i3-i3i+0)*(info%xm+2*sw)+sw+i2-i2i+0)*info%dof<br>
&gt;&gt;<br>
&gt;&gt;             i0p0=1+((sw+i3-i3i+0)*(info%xm+2*sw)+sw+i2-i2i+1)*info%dof<br>
&gt;&gt;             i00p=1+((sw+i3-i3i+1)*(info%xm+2*sw)+sw+i2-i2i+0)*info%dof<br>
&gt;&gt;             i0m0=1+((sw+i3-i3i+0)*(info%xm+2*sw)+sw+i2-i2i-1)*info%dof<br>
&gt;&gt;             i00m=1+((sw+i3-i3i-1)*(info%xm+2*sw)+sw+i2-i2i+0)*info%dof<br>
&gt;&gt;<br>
&gt;&gt;             px(i000+IU1)=px(i000+IU1)+ &amp;<br>
&gt;&gt;                     (pb(i000+IU1)-((+(px(i0p0+IU1)-px(i000+IU1)<br>
&gt;&gt; )-(px(i000+IU1)-px(i0m0+IU1) )) &amp;<br>
&gt;&gt;<br>
&gt;&gt; +(+(px(i00p+IU1)-px(i000+IU1) )-(px(i000+IU1)-px(i00m+IU1) )))) /<br>
&gt;&gt; (-4._8)<br>
&gt;&gt;          END DO<br>
&gt;&gt;<br>
&gt;&gt;          ! publish new values of x for its global vector<br>
&gt;&gt;          CALL DALocalToGlobal(c%daul(1+level),lx,INSERT_VALUES,x,ierr)<br>
&gt;&gt;<br>
&gt;&gt;       END DO<br>
&gt;&gt;    END DO<br>
&gt;&gt;<br>
&gt;&gt;    ! dispose of the local vectors<br>
&gt;&gt;    CALL VecRestoreArrayF90(lx,px,ierr)<br>
&gt;&gt;    CALL VecRestoreArrayF90(lb,pb,ierr)<br>
&gt;&gt;    CALL DARestoreLocalVector(c%daul(1+level),lx,ierr)<br>
&gt;&gt;    CALL DARestoreLocalVector(c%daul(1+level),lb,ierr)<br>
&gt;&gt;<br>
&gt;&gt;  END SUBROUTINE matrixsmooth<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Could this be changed to something like:<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;    ... INITIALIZE...<br>
&gt;&gt;<br>
&gt;&gt;    CALL DAGlobalToLocalBegin(c%daul(1+c%level),x,INSERT_VALUES,lx,ierr)<br>
&gt;&gt;    CALL DAGlobalToLocalEnd(c%daul(1+c%level),x,INSERT_VALUES,lx,ierr)<br>
&gt;&gt;<br>
&gt;&gt;   ! fast smoothing (relaxation) its=number of iteration<br>
&gt;&gt;    DO k=1,its<br>
&gt;&gt;       ! Red-Black Gauss-Siedel scheme<br>
&gt;&gt;       DO p=0,1<br>
&gt;&gt;          ! smoothing (relaxation)<br>
&gt;&gt;          DO i=istart+p+off,iend-1,info%dof*2<br>
&gt;&gt;             ...STENCIL OPERATION...<br>
&gt;&gt;          END DO<br>
&gt;&gt;<br>
&gt;&gt;          ...UPDATE GHOST POINTS...<br>
&gt;&gt;<br>
&gt;&gt;       END DO<br>
&gt;&gt;    END DO<br>
&gt;&gt;<br>
&gt;&gt;   ! publish new values of x for its global vector<br>
&gt;&gt;    CALL DALocalToGlobal(c%daul(1+level),lx,INSERT_VALUES,x,ierr)<br>
&gt;&gt;<br>
&gt;&gt;   ...CLEAN MEMORY...<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Any recommendation?<br>
&gt;&gt;<br>
&gt;&gt; Best wishes,<br>
&gt;&gt; Sylvain Barbot<br>
&gt;<br>
&gt;<br>
&gt;<br>
<span class="HOEnZb"><font color="#888888">&gt;<br>
&gt; --<br>
&gt; What most experimenters take for granted before they begin their experiments<br>
&gt; is infinitely more interesting than any results to which their experiments<br>
&gt; lead.<br>
&gt; -- Norbert Wiener<br>
</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br>What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead.<br>
-- Norbert Wiener<br>