197929ea7SJunchao Zhang static char help[]= " Test VecScatterRemap() on various vecscatter. \n\ 297929ea7SJunchao Zhang We may do optimization based on index patterns. After index remapping by VecScatterRemap(), we need to \n\ 397929ea7SJunchao Zhang make sure the vecscatter works as expected with the optimizaiton. \n\ 497929ea7SJunchao Zhang VecScatterRemap() does not support all kinds of vecscatters. In addition, it only supports remapping \n\ 56aad120cSJose E. Roman entries where we read the data (i.e., todata in parallel scatter, fromdata in sequential scatter). This test \n\ 66aad120cSJose E. Roman tests VecScatterRemap on parallel to parallel (PtoP) vecscatter, sequential general to sequential \n\ 797929ea7SJunchao Zhang general (SGToSG) vecscatter and sequential general to sequential stride 1 (SGToSS_Stride1) vecscatter.\n\n"; 897929ea7SJunchao Zhang 997929ea7SJunchao Zhang #include <petscvec.h> 1097929ea7SJunchao Zhang 1197929ea7SJunchao Zhang int main(int argc,char **argv) 1297929ea7SJunchao Zhang { 1397929ea7SJunchao Zhang PetscInt i,n,*ix,*iy,*tomap,start; 1497929ea7SJunchao Zhang Vec x,y; 1597929ea7SJunchao Zhang PetscMPIInt nproc,rank; 1697929ea7SJunchao Zhang IS isx,isy; 1797929ea7SJunchao Zhang const PetscInt *ranges; 1897929ea7SJunchao Zhang VecScatter vscat; 1997929ea7SJunchao Zhang 2097929ea7SJunchao Zhang PetscFunctionBegin; 21*327415f7SBarry Smith PetscFunctionBeginUser; 229566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&nproc)); 249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 2597929ea7SJunchao Zhang 2608401ef6SPierre Jolivet PetscCheck(nproc == 2,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This test must run with exactly two MPI ranks"); 2797929ea7SJunchao Zhang 2897929ea7SJunchao Zhang /* ==================================================================== 2997929ea7SJunchao Zhang (1) test VecScatterRemap on a parallel to parallel (PtoP) vecscatter 3097929ea7SJunchao Zhang ==================================================================== 3197929ea7SJunchao Zhang */ 3297929ea7SJunchao Zhang 3397929ea7SJunchao Zhang n = 64; /* long enough to trigger memcpy optimizations both in local scatter and remote scatter */ 3497929ea7SJunchao Zhang 3597929ea7SJunchao Zhang /* create two MPI vectors x, y of length n=64, N=128 */ 369566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(PETSC_COMM_WORLD,n,PETSC_DECIDE,&x)); 379566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x,&y)); 3897929ea7SJunchao Zhang 3997929ea7SJunchao Zhang /* Initialize x as {0~127} */ 409566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRanges(x,&ranges)); 419566063dSJacob Faibussowitsch for (i=ranges[rank]; i<ranges[rank+1]; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i,INSERT_VALUES)); 429566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(x)); 439566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(x)); 4497929ea7SJunchao Zhang 4597929ea7SJunchao Zhang /* create two general index sets isx = {0~127} and isy = {32~63,64~95,96~127,0~31}. isx is sequential, but we use 4697929ea7SJunchao Zhang it as general and let PETSc detect the pattern and optimize it. indices in isy are set to make the vecscatter 4797929ea7SJunchao Zhang have both local scatter and remote scatter (i.e., MPI communication) 4897929ea7SJunchao Zhang */ 499566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n,&ix,n,&iy)); 5097929ea7SJunchao Zhang start = ranges[rank]; 5197929ea7SJunchao Zhang for (i=ranges[rank]; i<ranges[rank+1]; i++) ix[i-start] = i; 529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,n,ix,PETSC_COPY_VALUES,&isx)); 5397929ea7SJunchao Zhang 54dd400576SPatrick Sanan if (rank == 0) { for (i=0; i<n; i++) iy[i] = i+32; } 5597929ea7SJunchao Zhang else for (i=0; i<n/2; i++) { iy[i] = i+96; iy[i+n/2] = i; } 5697929ea7SJunchao Zhang 579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,n,iy,PETSC_COPY_VALUES,&isy)); 5897929ea7SJunchao Zhang 5997929ea7SJunchao Zhang /* create a vecscatter that shifts x to the tail by quater periodically and puts the results in y */ 609566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(x,isx,y,isy,&vscat)); 619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 6397929ea7SJunchao Zhang 6497929ea7SJunchao Zhang /* view y to check the result. y should be {Q3,Q0,Q1,Q2} of x, that is {96~127,0~31,32~63,64~95} */ 659566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Before VecScatterRemap on PtoP, MPI vector y is:\n")); 669566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 6797929ea7SJunchao Zhang 6897929ea7SJunchao Zhang /* now call the weird subroutine VecScatterRemap to slightly change the vecscatter. It changes where we read vector 6997929ea7SJunchao Zhang x entries to send out, but does not change the communication pattern (i.e., send/recv pairs and msg lengths). 7097929ea7SJunchao Zhang 716aad120cSJose E. Roman We create tomap as {32~63,0~31}. Originally, we read from indices {0~64} of the local x to send out. The remap 7297929ea7SJunchao Zhang does indices[i] = tomap[indices[i]]. Therefore, after the remap, we read from indices {32~63,0~31} of the local x. 7397929ea7SJunchao Zhang isy is unchanged. So, we will shift x to {Q2,Q1,Q0,Q3}, that is {64~95,32~63,0~31,96~127} 7497929ea7SJunchao Zhang */ 759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&tomap)); 7697929ea7SJunchao Zhang for (i=0; i<n/2; i++) { tomap[i] = i+n/2; tomap[i+n/2] = i; }; 779566063dSJacob Faibussowitsch PetscCall(VecScatterRemap(vscat,tomap,NULL)); 789566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 799566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 8097929ea7SJunchao Zhang 8197929ea7SJunchao Zhang /* view y to check the result. y should be {64~95,32~63,0~31,96~127} */ 829566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"After VecScatterRemap on PtoP, MPI vector y is:\n")); 839566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 8497929ea7SJunchao Zhang 8597929ea7SJunchao Zhang /* destroy everything before we recreate them in different types */ 869566063dSJacob Faibussowitsch PetscCall(PetscFree2(ix,iy)); 879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isx)); 909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isy)); 919566063dSJacob Faibussowitsch PetscCall(PetscFree(tomap)); 929566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&vscat)); 9397929ea7SJunchao Zhang 9497929ea7SJunchao Zhang /* ========================================================================================== 9597929ea7SJunchao Zhang (2) test VecScatterRemap on a sequential general to sequential general (SGToSG) vecscatter 9697929ea7SJunchao Zhang ========================================================================================== 9797929ea7SJunchao Zhang */ 9897929ea7SJunchao Zhang n = 64; /* long enough to trigger memcpy optimizations in local scatter */ 9997929ea7SJunchao Zhang 10097929ea7SJunchao Zhang /* create two seq vectors x, y of length n */ 1019566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,n,&x)); 1029566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x,&y)); 10397929ea7SJunchao Zhang 10497929ea7SJunchao Zhang /* Initialize x as {0~63} */ 1059566063dSJacob Faibussowitsch for (i=0; i<n; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i,INSERT_VALUES)); 1069566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(x)); 1079566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(x)); 10897929ea7SJunchao Zhang 10997929ea7SJunchao Zhang /* create two general index sets isx = isy = {0~63}, which are sequential, but we use them as 11097929ea7SJunchao Zhang general and let PETSc detect the pattern and optimize it */ 1119566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n,&ix,n,&iy)); 11297929ea7SJunchao Zhang for (i=0; i<n; i++) ix[i] = i; 1139566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,n,ix,PETSC_COPY_VALUES,&isx)); 1149566063dSJacob Faibussowitsch PetscCall(ISDuplicate(isx,&isy)); 11597929ea7SJunchao Zhang 11697929ea7SJunchao Zhang /* create a vecscatter that just copies x to y */ 1179566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(x,isx,y,isy,&vscat)); 1189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 1199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 12097929ea7SJunchao Zhang 12197929ea7SJunchao Zhang /* view y to check the result. y should be {0~63} */ 1229566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nBefore VecScatterRemap on SGToSG, SEQ vector y is:\n")); 1239566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 12497929ea7SJunchao Zhang 12597929ea7SJunchao Zhang /* now call the weird subroutine VecScatterRemap to slightly change the vecscatter. 12697929ea7SJunchao Zhang 1276aad120cSJose E. Roman Create tomap as {32~63,0~31}. Originally, we read from indices {0~64} of seq x to write to y. The remap 12897929ea7SJunchao Zhang does indices[i] = tomap[indices[i]]. Therefore, after the remap, we read from indices{32~63,0~31} of seq x. 12997929ea7SJunchao Zhang */ 1309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&tomap)); 13197929ea7SJunchao Zhang for (i=0; i<n/2; i++) { tomap[i] = i+n/2; tomap[i+n/2] = i; }; 1329566063dSJacob Faibussowitsch PetscCall(VecScatterRemap(vscat,tomap,NULL)); 1339566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 1349566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 13597929ea7SJunchao Zhang 13697929ea7SJunchao Zhang /* view y to check the result. y should be {32~63,0~31} */ 1379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"After VecScatterRemap on SGToSG, SEQ vector y is:\n")); 1389566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 13997929ea7SJunchao Zhang 14097929ea7SJunchao Zhang /* destroy everything before we recreate them in different types */ 1419566063dSJacob Faibussowitsch PetscCall(PetscFree2(ix,iy)); 1429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 1439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 1449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isx)); 1459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isy)); 1469566063dSJacob Faibussowitsch PetscCall(PetscFree(tomap)); 1479566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&vscat)); 14897929ea7SJunchao Zhang 14997929ea7SJunchao Zhang /* =================================================================================================== 15097929ea7SJunchao Zhang (3) test VecScatterRemap on a sequential general to sequential stride 1 (SGToSS_Stride1) vecscatter 15197929ea7SJunchao Zhang =================================================================================================== 15297929ea7SJunchao Zhang */ 15397929ea7SJunchao Zhang n = 64; /* long enough to trigger memcpy optimizations in local scatter */ 15497929ea7SJunchao Zhang 15597929ea7SJunchao Zhang /* create two seq vectors x of length n, and y of length n/2 */ 1569566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,n,&x)); 1579566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,n/2,&y)); 15897929ea7SJunchao Zhang 15997929ea7SJunchao Zhang /* Initialize x as {0~63} */ 1609566063dSJacob Faibussowitsch for (i=0; i<n; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i,INSERT_VALUES)); 1619566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(x)); 1629566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(x)); 16397929ea7SJunchao Zhang 16497929ea7SJunchao Zhang /* create a general index set isx = {0:63:2}, which actually is a stride IS with first=0, n=32, step=2, 16597929ea7SJunchao Zhang but we use it as general and let PETSc detect the pattern and optimize it. */ 1669566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n/2,&ix,n/2,&iy)); 16797929ea7SJunchao Zhang for (i=0; i<n/2; i++) ix[i] = i*2; 1689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,n/2,ix,PETSC_COPY_VALUES,&isx)); 16997929ea7SJunchao Zhang 17097929ea7SJunchao Zhang /* create a stride1 index set isy = {0~31}. We intentionally set the step to 1 to trigger optimizations */ 1719566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,32,0,1,&isy)); 17297929ea7SJunchao Zhang 17397929ea7SJunchao Zhang /* create a vecscatter that just copies even entries of x to y */ 1749566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(x,isx,y,isy,&vscat)); 1759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 1769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 17797929ea7SJunchao Zhang 17897929ea7SJunchao Zhang /* view y to check the result. y should be {0:63:2} */ 1799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nBefore VecScatterRemap on SGToSS_Stride1, SEQ vector y is:\n")); 1809566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 18197929ea7SJunchao Zhang 18297929ea7SJunchao Zhang /* now call the weird subroutine VecScatterRemap to slightly change the vecscatter. 18397929ea7SJunchao Zhang 1846aad120cSJose E. Roman Create tomap as {32~63,0~31}. Originally, we read from indices{0:63:2} of seq x to write to y. The remap 18597929ea7SJunchao Zhang does indices[i] = tomap[indices[i]]. Therefore, after the remap, we read from indices{32:63:2,0:31:2} of seq x. 18697929ea7SJunchao Zhang */ 1879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n,&tomap)); 18897929ea7SJunchao Zhang for (i=0; i<n/2; i++) { tomap[i] = i+n/2; tomap[i+n/2] = i; }; 1899566063dSJacob Faibussowitsch PetscCall(VecScatterRemap(vscat,tomap,NULL)); 1909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 1919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(vscat,x,y,INSERT_VALUES,SCATTER_FORWARD)); 19297929ea7SJunchao Zhang 19397929ea7SJunchao Zhang /* view y to check the result. y should be {32:63:2,0:31:2} */ 1949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD,"After VecScatterRemap on SGToSS_Stride1, SEQ vector y is:\n")); 1959566063dSJacob Faibussowitsch PetscCall(VecView(y,PETSC_VIEWER_STDOUT_WORLD)); 19697929ea7SJunchao Zhang 19797929ea7SJunchao Zhang /* destroy everything before PetscFinalize */ 1989566063dSJacob Faibussowitsch PetscCall(PetscFree2(ix,iy)); 1999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 2009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isx)); 2029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isy)); 2039566063dSJacob Faibussowitsch PetscCall(PetscFree(tomap)); 2049566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&vscat)); 20597929ea7SJunchao Zhang 2069566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 207b122ec5aSJacob Faibussowitsch return 0; 20897929ea7SJunchao Zhang } 20997929ea7SJunchao Zhang 21097929ea7SJunchao Zhang /*TEST 21197929ea7SJunchao Zhang 21297929ea7SJunchao Zhang test: 21397929ea7SJunchao Zhang suffix: 1 21497929ea7SJunchao Zhang nsize: 2 21597929ea7SJunchao Zhang diff_args: -j 21697929ea7SJunchao Zhang requires: double 21797929ea7SJunchao Zhang TEST*/ 218