xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
1af0996ceSBarry Smith #include <petsc/private/sfimpl.h> /*I "petscsf.h" I*/
295fce210SBarry Smith 
395fce210SBarry Smith typedef struct _n_PetscSFDataLink *PetscSFDataLink;
495fce210SBarry Smith typedef struct _n_PetscSFWinLink  *PetscSFWinLink;
595fce210SBarry Smith 
695fce210SBarry Smith typedef struct {
795fce210SBarry Smith   PetscSFWindowSyncType   sync;   /* FENCE, LOCK, or ACTIVE synchronization */
85b0d146aSStefano Zampini   PetscSFDataLink         link;   /* List of MPI data types, lazily constructed for each data type */
995fce210SBarry Smith   PetscSFWinLink          wins;   /* List of active windows */
105b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor; /* Current PETSCSF_WINDOW_FLAVOR_ */
115b0d146aSStefano Zampini   PetscSF                 dynsf;
125b0d146aSStefano Zampini   MPI_Info                info;
1395fce210SBarry Smith } PetscSF_Window;
1495fce210SBarry Smith 
1595fce210SBarry Smith struct _n_PetscSFDataLink {
1695fce210SBarry Smith   MPI_Datatype    unit;
1795fce210SBarry Smith   MPI_Datatype    *mine;
1895fce210SBarry Smith   MPI_Datatype    *remote;
1995fce210SBarry Smith   PetscSFDataLink next;
2095fce210SBarry Smith };
2195fce210SBarry Smith 
2295fce210SBarry Smith struct _n_PetscSFWinLink {
2395fce210SBarry Smith   PetscBool               inuse;
2495fce210SBarry Smith   size_t                  bytes;
2595fce210SBarry Smith   void                    *addr;
265b0d146aSStefano Zampini   void                    *paddr;
2795fce210SBarry Smith   MPI_Win                 win;
28684a874aSStefano Zampini   MPI_Request             *reqs;
295b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
305b0d146aSStefano Zampini   MPI_Aint                *dyn_target_addr;
3195fce210SBarry Smith   PetscBool               epoch;
3295fce210SBarry Smith   PetscSFWinLink          next;
3395fce210SBarry Smith };
3495fce210SBarry Smith 
354c8fdceaSLisandro Dalcin const char *const PetscSFWindowSyncTypes[] = {"FENCE","LOCK","ACTIVE","PetscSFWindowSyncType","PETSCSF_WINDOW_SYNC_",NULL};
364c8fdceaSLisandro Dalcin const char *const PetscSFWindowFlavorTypes[] = {"CREATE","DYNAMIC","ALLOCATE","SHARED","PetscSFWindowFlavorType","PETSCSF_WINDOW_FLAVOR_",NULL};
3795fce210SBarry Smith 
38820f2d46SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPI_Allreduce) */
3995fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
4095fce210SBarry Smith {
4195fce210SBarry Smith   PetscFunctionBegin;
4295fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4395fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4495fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4595fce210SBarry Smith   PetscFunctionReturn(0);
4695fce210SBarry Smith }
4795fce210SBarry Smith 
4895fce210SBarry Smith /*@C
4995fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5095fce210SBarry Smith 
5195fce210SBarry Smith    Not Collective
5295fce210SBarry Smith 
534165533cSJose E. Roman    Input Parameters:
5495fce210SBarry Smith +  sf - star forest
5595fce210SBarry Smith -  unit - data type for each node
5695fce210SBarry Smith 
574165533cSJose E. Roman    Output Parameters:
5895fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5995fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6095fce210SBarry Smith 
6195fce210SBarry Smith    Level: developer
6295fce210SBarry Smith 
6395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6495fce210SBarry Smith @*/
6595fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6695fce210SBarry Smith {
6795fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6895fce210SBarry Smith   PetscErrorCode    ierr;
6995fce210SBarry Smith   PetscSFDataLink   link;
7095fce210SBarry Smith   PetscInt          i,nranks;
7195fce210SBarry Smith   const PetscInt    *roffset,*rmine,*rremote;
7295fce210SBarry Smith   const PetscMPIInt *ranks;
7395fce210SBarry Smith 
7495fce210SBarry Smith   PetscFunctionBegin;
7595fce210SBarry Smith   /* Look for types in cache */
7695fce210SBarry Smith   for (link=w->link; link; link=link->next) {
7795fce210SBarry Smith     PetscBool match;
7895fce210SBarry Smith     ierr = MPIPetsc_Type_compare(unit,link->unit,&match);CHKERRQ(ierr);
7995fce210SBarry Smith     if (match) {
8095fce210SBarry Smith       *localtypes  = link->mine;
8195fce210SBarry Smith       *remotetypes = link->remote;
8295fce210SBarry Smith       PetscFunctionReturn(0);
8395fce210SBarry Smith     }
8495fce210SBarry Smith   }
8595fce210SBarry Smith 
8695fce210SBarry Smith   /* Create new composite types for each send rank */
87dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr);
8895dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
89ffc4695bSBarry Smith   ierr = MPI_Type_dup(unit,&link->unit);CHKERRMPI(ierr);
90dcca6d9dSJed Brown   ierr = PetscMalloc2(nranks,&link->mine,nranks,&link->remote);CHKERRQ(ierr);
9195fce210SBarry Smith   for (i=0; i<nranks; i++) {
925b0d146aSStefano Zampini     PetscInt    rcount = roffset[i+1] - roffset[i];
9395fce210SBarry Smith     PetscMPIInt *rmine,*rremote;
9495fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9595fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9695fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9795fce210SBarry Smith #else
9895fce210SBarry Smith     PetscInt j;
99dcca6d9dSJed Brown     ierr = PetscMalloc2(rcount,&rmine,rcount,&rremote);CHKERRQ(ierr);
10095fce210SBarry Smith     for (j=0; j<rcount; j++) {
10195fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j);CHKERRQ(ierr);
10295fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j);CHKERRQ(ierr);
10395fce210SBarry Smith     }
10495fce210SBarry Smith #endif
1055b0d146aSStefano Zampini 
106ffc4695bSBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]);CHKERRMPI(ierr);
107ffc4695bSBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]);CHKERRMPI(ierr);
10895fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
10995fce210SBarry Smith     ierr = PetscFree2(rmine,rremote);CHKERRQ(ierr);
11095fce210SBarry Smith #endif
111ffc4695bSBarry Smith     ierr = MPI_Type_commit(&link->mine[i]);CHKERRMPI(ierr);
112ffc4695bSBarry Smith     ierr = MPI_Type_commit(&link->remote[i]);CHKERRMPI(ierr);
11395fce210SBarry Smith   }
11495fce210SBarry Smith   link->next = w->link;
11595fce210SBarry Smith   w->link    = link;
11695fce210SBarry Smith 
11795fce210SBarry Smith   *localtypes  = link->mine;
11895fce210SBarry Smith   *remotetypes = link->remote;
11995fce210SBarry Smith   PetscFunctionReturn(0);
12095fce210SBarry Smith }
12195fce210SBarry Smith 
12295fce210SBarry Smith /*@C
1235b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
1245b0d146aSStefano Zampini 
1255b0d146aSStefano Zampini    Logically Collective
1265b0d146aSStefano Zampini 
1274165533cSJose E. Roman    Input Parameters:
1285b0d146aSStefano Zampini +  sf - star forest for communication
1295b0d146aSStefano Zampini -  flavor - flavor type
1305b0d146aSStefano Zampini 
1315b0d146aSStefano Zampini    Options Database Key:
1325b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
1335b0d146aSStefano Zampini 
1345b0d146aSStefano Zampini    Level: advanced
1355b0d146aSStefano Zampini 
1365b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
1375b0d146aSStefano Zampini 
1385b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1395b0d146aSStefano Zampini 
1405b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_DYNAMIC: uses MPI_Win_create_dynamic/MPI_Win_attach and tries to reuse windows by comparing the root array. Intended to be used on repeated applications of the same SF, e.g.
1415b0d146aSStefano Zampini        for i=1 to K
1425b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1435b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1445b0d146aSStefano Zampini          ...
1455b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
1465b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
1475b0d146aSStefano Zampini        endfor
1485b0d146aSStefano Zampini        The following pattern will instead raise an error
1495b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1505b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1515b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
1525b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
1535b0d146aSStefano Zampini 
1545b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1555b0d146aSStefano Zampini 
1565b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
1575b0d146aSStefano Zampini 
1585b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType()
1595b0d146aSStefano Zampini @*/
1605b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)
1615b0d146aSStefano Zampini {
1625b0d146aSStefano Zampini   PetscErrorCode ierr;
1635b0d146aSStefano Zampini 
1645b0d146aSStefano Zampini   PetscFunctionBegin;
1655b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
1665b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf,flavor,2);
1675b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor));CHKERRQ(ierr);
1685b0d146aSStefano Zampini   PetscFunctionReturn(0);
1695b0d146aSStefano Zampini }
1705b0d146aSStefano Zampini 
1715b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)
1725b0d146aSStefano Zampini {
1735b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
1745b0d146aSStefano Zampini 
1755b0d146aSStefano Zampini   PetscFunctionBegin;
1765b0d146aSStefano Zampini   w->flavor = flavor;
1775b0d146aSStefano Zampini   PetscFunctionReturn(0);
1785b0d146aSStefano Zampini }
1795b0d146aSStefano Zampini 
1805b0d146aSStefano Zampini /*@C
1815b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
1825b0d146aSStefano Zampini 
1835b0d146aSStefano Zampini    Logically Collective
1845b0d146aSStefano Zampini 
1854165533cSJose E. Roman    Input Parameter:
1865b0d146aSStefano Zampini .  sf - star forest for communication
1875b0d146aSStefano Zampini 
1884165533cSJose E. Roman    Output Parameter:
1895b0d146aSStefano Zampini .  flavor - flavor type
1905b0d146aSStefano Zampini 
1915b0d146aSStefano Zampini    Level: advanced
1925b0d146aSStefano Zampini 
1935b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType()
1945b0d146aSStefano Zampini @*/
1955b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor)
1965b0d146aSStefano Zampini {
1975b0d146aSStefano Zampini   PetscErrorCode ierr;
1985b0d146aSStefano Zampini 
1995b0d146aSStefano Zampini   PetscFunctionBegin;
2005b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
2015b0d146aSStefano Zampini   PetscValidPointer(flavor,2);
2025b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor));CHKERRQ(ierr);
2035b0d146aSStefano Zampini   PetscFunctionReturn(0);
2045b0d146aSStefano Zampini }
2055b0d146aSStefano Zampini 
2065b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor)
2075b0d146aSStefano Zampini {
2085b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
2095b0d146aSStefano Zampini 
2105b0d146aSStefano Zampini   PetscFunctionBegin;
2115b0d146aSStefano Zampini   *flavor = w->flavor;
2125b0d146aSStefano Zampini   PetscFunctionReturn(0);
2135b0d146aSStefano Zampini }
2145b0d146aSStefano Zampini 
2155b0d146aSStefano Zampini /*@C
2165b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
21795fce210SBarry Smith 
21895fce210SBarry Smith    Logically Collective
21995fce210SBarry Smith 
2204165533cSJose E. Roman    Input Parameters:
22195fce210SBarry Smith +  sf - star forest for communication
22295fce210SBarry Smith -  sync - synchronization type
22395fce210SBarry Smith 
22495fce210SBarry Smith    Options Database Key:
22560263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
22695fce210SBarry Smith 
22795fce210SBarry Smith    Level: advanced
22895fce210SBarry Smith 
22995fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType()
23095fce210SBarry Smith @*/
23195fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)
23295fce210SBarry Smith {
23395fce210SBarry Smith   PetscErrorCode ierr;
23495fce210SBarry Smith 
23595fce210SBarry Smith   PetscFunctionBegin;
23695fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
23795fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf,sync,2);
2385b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync));CHKERRQ(ierr);
23995fce210SBarry Smith   PetscFunctionReturn(0);
24095fce210SBarry Smith }
24195fce210SBarry Smith 
242f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)
24395fce210SBarry Smith {
24495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
24595fce210SBarry Smith 
24695fce210SBarry Smith   PetscFunctionBegin;
24795fce210SBarry Smith   w->sync = sync;
24895fce210SBarry Smith   PetscFunctionReturn(0);
24995fce210SBarry Smith }
25095fce210SBarry Smith 
25195fce210SBarry Smith /*@C
2525b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
25395fce210SBarry Smith 
25495fce210SBarry Smith    Logically Collective
25595fce210SBarry Smith 
2564165533cSJose E. Roman    Input Parameter:
25795fce210SBarry Smith .  sf - star forest for communication
25895fce210SBarry Smith 
2594165533cSJose E. Roman    Output Parameter:
26095fce210SBarry Smith .  sync - synchronization type
26195fce210SBarry Smith 
26295fce210SBarry Smith    Level: advanced
26395fce210SBarry Smith 
2645b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType()
26595fce210SBarry Smith @*/
26695fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync)
26795fce210SBarry Smith {
26895fce210SBarry Smith   PetscErrorCode ierr;
26995fce210SBarry Smith 
27095fce210SBarry Smith   PetscFunctionBegin;
27195fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
27295fce210SBarry Smith   PetscValidPointer(sync,2);
273163d334eSBarry Smith   ierr = PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync));CHKERRQ(ierr);
27495fce210SBarry Smith   PetscFunctionReturn(0);
27595fce210SBarry Smith }
27695fce210SBarry Smith 
277f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync)
27895fce210SBarry Smith {
27995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
28095fce210SBarry Smith 
28195fce210SBarry Smith   PetscFunctionBegin;
28295fce210SBarry Smith   *sync = w->sync;
28395fce210SBarry Smith   PetscFunctionReturn(0);
28495fce210SBarry Smith }
28595fce210SBarry Smith 
28695fce210SBarry Smith /*@C
2875b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
2885b0d146aSStefano Zampini 
2895b0d146aSStefano Zampini    Logically Collective
2905b0d146aSStefano Zampini 
2914165533cSJose E. Roman    Input Parameters:
2925b0d146aSStefano Zampini +  sf - star forest for communication
2935b0d146aSStefano Zampini -  info - MPI_Info handle
2945b0d146aSStefano Zampini 
2955b0d146aSStefano Zampini    Level: advanced
2965b0d146aSStefano Zampini 
2975b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
2985b0d146aSStefano Zampini 
2995b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo()
3005b0d146aSStefano Zampini @*/
3015b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)
3025b0d146aSStefano Zampini {
3035b0d146aSStefano Zampini   PetscErrorCode ierr;
3045b0d146aSStefano Zampini 
3055b0d146aSStefano Zampini   PetscFunctionBegin;
3065b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3075b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info));CHKERRQ(ierr);
3085b0d146aSStefano Zampini   PetscFunctionReturn(0);
3095b0d146aSStefano Zampini }
3105b0d146aSStefano Zampini 
3115b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)
3125b0d146aSStefano Zampini {
3135b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3145b0d146aSStefano Zampini   PetscErrorCode ierr;
3155b0d146aSStefano Zampini 
3165b0d146aSStefano Zampini   PetscFunctionBegin;
3175b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
318ffc4695bSBarry Smith     ierr = MPI_Info_free(&w->info);CHKERRMPI(ierr);
3195b0d146aSStefano Zampini   }
3205b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
321ffc4695bSBarry Smith     ierr = MPI_Info_dup(info,&w->info);CHKERRMPI(ierr);
3225b0d146aSStefano Zampini   }
3235b0d146aSStefano Zampini   PetscFunctionReturn(0);
3245b0d146aSStefano Zampini }
3255b0d146aSStefano Zampini 
3265b0d146aSStefano Zampini /*@C
3275b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
3285b0d146aSStefano Zampini 
3295b0d146aSStefano Zampini    Logically Collective
3305b0d146aSStefano Zampini 
3314165533cSJose E. Roman    Input Parameter:
3325b0d146aSStefano Zampini .  sf - star forest for communication
3335b0d146aSStefano Zampini 
3344165533cSJose E. Roman    Output Parameter:
3355b0d146aSStefano Zampini .  info - MPI_Info handle
3365b0d146aSStefano Zampini 
3375b0d146aSStefano Zampini    Level: advanced
3385b0d146aSStefano Zampini 
3395b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
3405b0d146aSStefano Zampini 
3415b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo()
3425b0d146aSStefano Zampini @*/
3435b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info)
3445b0d146aSStefano Zampini {
3455b0d146aSStefano Zampini   PetscErrorCode ierr;
3465b0d146aSStefano Zampini 
3475b0d146aSStefano Zampini   PetscFunctionBegin;
3485b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3495b0d146aSStefano Zampini   PetscValidPointer(info,2);
3505b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info));CHKERRQ(ierr);
3515b0d146aSStefano Zampini   PetscFunctionReturn(0);
3525b0d146aSStefano Zampini }
3535b0d146aSStefano Zampini 
3545b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info)
3555b0d146aSStefano Zampini {
3565b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3575b0d146aSStefano Zampini 
3585b0d146aSStefano Zampini   PetscFunctionBegin;
3595b0d146aSStefano Zampini   *info = w->info;
3605b0d146aSStefano Zampini   PetscFunctionReturn(0);
3615b0d146aSStefano Zampini }
3625b0d146aSStefano Zampini 
3635b0d146aSStefano Zampini /*
36495fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
36595fce210SBarry Smith 
36695fce210SBarry Smith    Collective on PetscSF
36795fce210SBarry Smith 
3684165533cSJose E. Roman    Input Parameters:
36995fce210SBarry Smith +  sf - star forest
37095fce210SBarry Smith .  unit - data type
37195fce210SBarry Smith .  array - array to be sent
3725b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
37395fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
3745b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
3755b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
376684a874aSStefano Zampini -  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
37795fce210SBarry Smith 
3784165533cSJose E. Roman    Output Parameters:
379684a874aSStefano Zampini +  target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only)
380684a874aSStefano Zampini +  reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only)
381684a874aSStefano Zampini -  win - window
38295fce210SBarry Smith 
38395fce210SBarry Smith    Level: developer
384dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes()
3855b0d146aSStefano Zampini */
386684a874aSStefano Zampini static PetscErrorCode PetscSFGetWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscMPIInt postassert,PetscMPIInt startassert,const MPI_Aint **target_disp, MPI_Request **reqs, MPI_Win *win)
38795fce210SBarry Smith {
38895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
38995fce210SBarry Smith   PetscErrorCode ierr;
39095fce210SBarry Smith   MPI_Aint       lb,lb_true,bytes,bytes_true;
39195fce210SBarry Smith   PetscSFWinLink link;
392d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
3935b0d146aSStefano Zampini   MPI_Aint       winaddr;
3945b0d146aSStefano Zampini   PetscInt       nranks;
395d547623eSJunchao Zhang #endif
3965b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
3975b0d146aSStefano Zampini   PetscBool      dummy[2];
3985b0d146aSStefano Zampini   MPI_Aint       wsize;
39995fce210SBarry Smith 
40095fce210SBarry Smith   PetscFunctionBegin;
401ffc4695bSBarry Smith   ierr = MPI_Type_get_extent(unit,&lb,&bytes);CHKERRMPI(ierr);
402ffc4695bSBarry Smith   ierr = MPI_Type_get_true_extent(unit,&lb_true,&bytes_true);CHKERRMPI(ierr);
403*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(lb != 0 || lb_true != 0,PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with nonzero lower bound, write petsc-maint@mcs.anl.gov if you want this feature");
404*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(bytes != bytes_true,PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with modified extent, write petsc-maint@mcs.anl.gov if you want this feature");
4055b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
4065b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
4075b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
4085b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
4095b0d146aSStefano Zampini     switch (w->flavor) {
4105b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_DYNAMIC: /* check available matching array, error if in use (we additionally check that the matching condition is the same across processes) */
4115b0d146aSStefano Zampini       if (array == link->addr) {
41276bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
4135b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
4145b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
415ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
416ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
417*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(dummy[0] != dummy[1],PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
41876bd3646SJed Brown         }
419*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(link->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
420*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(epoch && link->epoch,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
4215b0d146aSStefano Zampini         winok = PETSC_TRUE;
4225b0d146aSStefano Zampini         link->paddr = array;
42376bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
4245b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4255b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
426ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
427ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
428*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dummy[0] != dummy[1],PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
4295b0d146aSStefano Zampini       }
4305b0d146aSStefano Zampini       break;
4315b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4325b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4335b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4345b0d146aSStefano Zampini         update = PETSC_TRUE;
4355b0d146aSStefano Zampini         link->paddr = array;
4365b0d146aSStefano Zampini         winok = PETSC_TRUE;
4375b0d146aSStefano Zampini       }
4385b0d146aSStefano Zampini       break;
43998921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4405b0d146aSStefano Zampini     }
4415b0d146aSStefano Zampini     if (winok) {
4425b0d146aSStefano Zampini       *win = link->win;
4437d3de750SJacob Faibussowitsch       ierr = PetscInfo(sf,"Reusing window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4445b0d146aSStefano Zampini       goto found;
4455b0d146aSStefano Zampini     }
4465b0d146aSStefano Zampini   }
4475b0d146aSStefano Zampini 
4485b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
44995dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
45095fce210SBarry Smith   link->bytes           = bytes;
45195fce210SBarry Smith   link->next            = w->wins;
4525b0d146aSStefano Zampini   link->flavor          = w->flavor;
4535b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
454684a874aSStefano Zampini   link->reqs            = NULL;
45595fce210SBarry Smith   w->wins               = link;
456684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
457684a874aSStefano Zampini     PetscInt i;
458684a874aSStefano Zampini 
459684a874aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&link->reqs);CHKERRQ(ierr);
460684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
461684a874aSStefano Zampini   }
4625b0d146aSStefano Zampini   switch (w->flavor) {
4635b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
464ffc4695bSBarry Smith     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4655b0d146aSStefano Zampini     link->addr  = array;
4665b0d146aSStefano Zampini     link->paddr = array;
4675b0d146aSStefano Zampini     break;
468d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
4695b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
470ffc4695bSBarry Smith     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4715b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
472ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRMPI(ierr);
4735b0d146aSStefano Zampini #else
474ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRMPI(ierr);
4755b0d146aSStefano Zampini #endif
4765b0d146aSStefano Zampini     link->addr  = array;
4775b0d146aSStefano Zampini     link->paddr = array;
478*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!w->dynsf,PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4795b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
4805b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4815b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
482ffc4695bSBarry Smith     ierr = MPI_Get_address(array,&winaddr);CHKERRMPI(ierr);
483ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE);CHKERRQ(ierr);
484ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE);CHKERRQ(ierr);
4855b0d146aSStefano Zampini     break;
4865b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
487ffc4695bSBarry Smith     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(ierr);
4885b0d146aSStefano Zampini     update = PETSC_TRUE;
4895b0d146aSStefano Zampini     link->paddr = array;
4905b0d146aSStefano Zampini     break;
491d547623eSJunchao Zhang #endif
4925b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4935b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
494ffc4695bSBarry Smith     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(ierr);
4955b0d146aSStefano Zampini     update = PETSC_TRUE;
4965b0d146aSStefano Zampini     link->paddr = array;
4975b0d146aSStefano Zampini     break;
4985b0d146aSStefano Zampini #endif
49998921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
5005b0d146aSStefano Zampini   }
5017d3de750SJacob Faibussowitsch   ierr = PetscInfo(sf,"New window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
50295fce210SBarry Smith   *win = link->win;
50395fce210SBarry Smith 
5045b0d146aSStefano Zampini found:
5055b0d146aSStefano Zampini 
506684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
507684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
508684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
509684a874aSStefano Zampini     PetscMPIInt rank;
510684a874aSStefano Zampini 
511ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRMPI(ierr);
512ffc4695bSBarry Smith     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win);CHKERRMPI(ierr);}
5135b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
5145b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
515ffc4695bSBarry Smith       ierr = MPI_Win_unlock(rank,*win);CHKERRMPI(ierr);
516ffc4695bSBarry Smith       ierr = MPI_Win_fence(0,*win);CHKERRMPI(ierr);
5175b0d146aSStefano Zampini     }
5185b0d146aSStefano Zampini   }
5195b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5205b0d146aSStefano Zampini   link->epoch = epoch;
52195fce210SBarry Smith   if (epoch) {
5225b0d146aSStefano Zampini     switch (sync) {
52395fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
524ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(ierr);
52595fce210SBarry Smith       break;
52695fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
52795fce210SBarry Smith       break;
52895fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
52995fce210SBarry Smith       MPI_Group   ingroup,outgroup;
5305b0d146aSStefano Zampini       PetscMPIInt isize,osize;
5315b0d146aSStefano Zampini 
5325b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
5335b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5345b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5355b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5365b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5375b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5385b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5395b0d146aSStefano Zampini       */
54095fce210SBarry Smith       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
541ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
542ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
543ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRMPI(ierr);}
544ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRMPI(ierr);}
54595fce210SBarry Smith     } break;
54695fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
54795fce210SBarry Smith     }
54895fce210SBarry Smith   }
54995fce210SBarry Smith   PetscFunctionReturn(0);
55095fce210SBarry Smith }
55195fce210SBarry Smith 
5525b0d146aSStefano Zampini /*
55395fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
55495fce210SBarry Smith 
55595fce210SBarry Smith    Not Collective
55695fce210SBarry Smith 
5574165533cSJose E. Roman    Input Parameters:
55895fce210SBarry Smith +  sf - star forest
55995fce210SBarry Smith .  unit - data type
56095fce210SBarry Smith -  array - array with which the window is associated
56195fce210SBarry Smith 
5624165533cSJose E. Roman    Output Parameters:
563684a874aSStefano Zampini +  win - window
564684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
56595fce210SBarry Smith 
56695fce210SBarry Smith    Level: developer
56795fce210SBarry Smith 
56895fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
5695b0d146aSStefano Zampini */
570684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs)
57195fce210SBarry Smith {
57295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
57395fce210SBarry Smith   PetscSFWinLink link;
5745b0d146aSStefano Zampini   PetscErrorCode ierr;
57595fce210SBarry Smith 
57695fce210SBarry Smith   PetscFunctionBegin;
577c0cd0301SJed Brown   *win = MPI_WIN_NULL;
57895fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
5795b0d146aSStefano Zampini     if (array == link->paddr) {
5802abc8c78SJacob Faibussowitsch 
5817d3de750SJacob Faibussowitsch       ierr = PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
58295fce210SBarry Smith       *win = link->win;
583684a874aSStefano Zampini       *reqs = link->reqs;
58495fce210SBarry Smith       PetscFunctionReturn(0);
58595fce210SBarry Smith     }
58695fce210SBarry Smith   }
58795fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
58895fce210SBarry Smith }
58995fce210SBarry Smith 
5905b0d146aSStefano Zampini /*
59195fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
59295fce210SBarry Smith 
59395fce210SBarry Smith    Collective
59495fce210SBarry Smith 
5954165533cSJose E. Roman    Input Parameters:
59695fce210SBarry Smith +  sf - star forest
59795fce210SBarry Smith .  unit - data type
59895fce210SBarry Smith .  array - array associated with window
5995b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
60095fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
6015b0d146aSStefano Zampini .  update - if we have to update the local window array
60295fce210SBarry Smith -  win - window
60395fce210SBarry Smith 
60495fce210SBarry Smith    Level: developer
60595fce210SBarry Smith 
60695fce210SBarry Smith .seealso: PetscSFFindWindow()
6075b0d146aSStefano Zampini */
6085b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
60995fce210SBarry Smith {
61095fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
61195fce210SBarry Smith   PetscErrorCode          ierr;
61295fce210SBarry Smith   PetscSFWinLink          *p,link;
6135b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6145b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6155b0d146aSStefano Zampini   void*                   laddr;
6165b0d146aSStefano Zampini   size_t                  bytes;
61795fce210SBarry Smith 
61895fce210SBarry Smith   PetscFunctionBegin;
61995fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
62095fce210SBarry Smith     link = *p;
62195fce210SBarry Smith     if (*win == link->win) {
622*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(array != link->paddr,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
62395fce210SBarry Smith       if (epoch != link->epoch) {
624*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(epoch,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
62595fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
62695fce210SBarry Smith       }
6275b0d146aSStefano Zampini       laddr = link->addr;
6285b0d146aSStefano Zampini       flavor = link->flavor;
6295b0d146aSStefano Zampini       bytes = link->bytes;
6305b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6315b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
63295fce210SBarry Smith       goto found;
63395fce210SBarry Smith     }
63495fce210SBarry Smith   }
63595fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
63695fce210SBarry Smith 
63795fce210SBarry Smith found:
6387d3de750SJacob Faibussowitsch   ierr = PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
63995fce210SBarry Smith   if (epoch) {
6405b0d146aSStefano Zampini     switch (sync) {
64195fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
642ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(ierr);
64395fce210SBarry Smith       break;
6445b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6455b0d146aSStefano Zampini       break;
64695fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6475b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6485b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6495b0d146aSStefano Zampini 
6505b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6515b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6525b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6535b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6545b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6555b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6565b0d146aSStefano Zampini       */
6575b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
658ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
659ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
660ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_complete(*win);CHKERRMPI(ierr);}
661ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_wait(*win);CHKERRMPI(ierr);}
66295fce210SBarry Smith     } break;
66395fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
66495fce210SBarry Smith     }
66595fce210SBarry Smith   }
6665b0d146aSStefano Zampini   if (update) {
6675b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
668ffc4695bSBarry Smith       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRMPI(ierr);
6695b0d146aSStefano Zampini     }
6705b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
6715b0d146aSStefano Zampini   }
6725b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6735b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6745b0d146aSStefano Zampini   link->paddr = NULL;
6755b0d146aSStefano Zampini   if (!reuse) {
676684a874aSStefano Zampini     ierr = PetscFree(link->dyn_target_addr);CHKERRQ(ierr);
677684a874aSStefano Zampini     ierr = PetscFree(link->reqs);CHKERRQ(ierr);
678ffc4695bSBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRMPI(ierr);
67995fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
68095fce210SBarry Smith     *win = MPI_WIN_NULL;
6815b0d146aSStefano Zampini   }
68295fce210SBarry Smith   PetscFunctionReturn(0);
68395fce210SBarry Smith }
68495fce210SBarry Smith 
68595fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
68695fce210SBarry Smith {
68795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
68895fce210SBarry Smith   PetscErrorCode ierr;
68995fce210SBarry Smith   MPI_Group      ingroup,outgroup;
69095fce210SBarry Smith 
69195fce210SBarry Smith   PetscFunctionBegin;
692b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
6935b0d146aSStefano Zampini   if (!w->dynsf) {
6945b0d146aSStefano Zampini     PetscInt    i;
6955b0d146aSStefano Zampini     PetscSFNode *remotes;
6965b0d146aSStefano Zampini 
6975b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
6985b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6995b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
7005b0d146aSStefano Zampini       remotes[i].index = 0;
7015b0d146aSStefano Zampini     }
7025b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
7035b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
7045b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
7055b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
7065b0d146aSStefano Zampini   }
70795fce210SBarry Smith   switch (w->sync) {
70895fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
70995fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
71095fce210SBarry Smith   default:
71195fce210SBarry Smith     break;
71295fce210SBarry Smith   }
71395fce210SBarry Smith   PetscFunctionReturn(0);
71495fce210SBarry Smith }
71595fce210SBarry Smith 
7164416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
71795fce210SBarry Smith {
71895fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
71995fce210SBarry Smith   PetscErrorCode          ierr;
7205b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
72195fce210SBarry Smith 
72295fce210SBarry Smith   PetscFunctionBegin;
723e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
72495fce210SBarry Smith   ierr = PetscOptionsEnum("-sf_window_sync","synchronization type to use for PetscSF Window communication","PetscSFWindowSetSyncType",PetscSFWindowSyncTypes,(PetscEnum)w->sync,(PetscEnum*)&w->sync,NULL);CHKERRQ(ierr);
7255b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
7265b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
72795fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
72895fce210SBarry Smith   PetscFunctionReturn(0);
72995fce210SBarry Smith }
73095fce210SBarry Smith 
73195fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
73295fce210SBarry Smith {
73395fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
73495fce210SBarry Smith   PetscErrorCode  ierr;
73595fce210SBarry Smith   PetscSFDataLink link,next;
73695fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
73795fce210SBarry Smith   PetscInt        i;
73895fce210SBarry Smith 
73995fce210SBarry Smith   PetscFunctionBegin;
74095fce210SBarry Smith   for (link=w->link; link; link=next) {
74195fce210SBarry Smith     next = link->next;
742ffc4695bSBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRMPI(ierr);
74395fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
744ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRMPI(ierr);
745ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRMPI(ierr);
74695fce210SBarry Smith     }
74795fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
74895fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
74995fce210SBarry Smith   }
75095fce210SBarry Smith   w->link = NULL;
75195fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
75295fce210SBarry Smith     wnext = wlink->next;
753*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(wlink->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7545b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
755684a874aSStefano Zampini     ierr = PetscFree(wlink->reqs);CHKERRQ(ierr);
756ffc4695bSBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRMPI(ierr);
75795fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
75895fce210SBarry Smith   }
75995fce210SBarry Smith   w->wins = NULL;
7605b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
7615b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
762ffc4695bSBarry Smith     ierr = MPI_Info_free(&w->info);CHKERRMPI(ierr);
7635b0d146aSStefano Zampini   }
76495fce210SBarry Smith   PetscFunctionReturn(0);
76595fce210SBarry Smith }
76695fce210SBarry Smith 
76795fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
76895fce210SBarry Smith {
76995fce210SBarry Smith   PetscErrorCode ierr;
77095fce210SBarry Smith 
77195fce210SBarry Smith   PetscFunctionBegin;
77229046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
77395fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
774bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
775bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
7765b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
7775b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
7785b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
7795b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
78095fce210SBarry Smith   PetscFunctionReturn(0);
78195fce210SBarry Smith }
78295fce210SBarry Smith 
78395fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
78495fce210SBarry Smith {
78595fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
78695fce210SBarry Smith   PetscErrorCode    ierr;
78795fce210SBarry Smith   PetscBool         iascii;
7885b0d146aSStefano Zampini   PetscViewerFormat format;
78995fce210SBarry Smith 
79095fce210SBarry Smith   PetscFunctionBegin;
7915b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
79295fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
79395fce210SBarry Smith   if (iascii) {
79462152dedSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  current flavor=%s synchronization=%s MultiSF sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);
7955b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7965b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7975b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7985b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7995b0d146aSStefano Zampini 
800ffc4695bSBarry Smith         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRMPI(ierr);
8015b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
8025b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
8035b0d146aSStefano Zampini           PetscMPIInt flag;
8045b0d146aSStefano Zampini 
805ffc4695bSBarry Smith           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRMPI(ierr);
806ffc4695bSBarry Smith           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRMPI(ierr);
807*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(!flag,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
8085b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
8095b0d146aSStefano Zampini         }
8105b0d146aSStefano Zampini       } else {
8115b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
8125b0d146aSStefano Zampini       }
8135b0d146aSStefano Zampini     }
81495fce210SBarry Smith   }
81595fce210SBarry Smith   PetscFunctionReturn(0);
81695fce210SBarry Smith }
81795fce210SBarry Smith 
81895fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
81995fce210SBarry Smith {
82095fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
82195fce210SBarry Smith   PetscErrorCode        ierr;
82295fce210SBarry Smith   PetscSFWindowSyncType synctype;
82395fce210SBarry Smith 
82495fce210SBarry Smith   PetscFunctionBegin;
82595fce210SBarry Smith   synctype = w->sync;
82695fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8275b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
82895fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
8295b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
8305b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
83195fce210SBarry Smith   PetscFunctionReturn(0);
83295fce210SBarry Smith }
83395fce210SBarry Smith 
834ad227feaSJunchao Zhang static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
83595fce210SBarry Smith {
83695fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
83795fce210SBarry Smith   PetscErrorCode     ierr;
83895fce210SBarry Smith   PetscInt           i,nranks;
83995fce210SBarry Smith   const PetscMPIInt  *ranks;
8405b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
84195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
842684a874aSStefano Zampini   MPI_Request        *reqs;
84395fce210SBarry Smith   MPI_Win            win;
84495fce210SBarry Smith 
84595fce210SBarry Smith   PetscFunctionBegin;
846*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(op != MPI_REPLACE,PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
847dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
84895fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
849684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&reqs,&win);CHKERRQ(ierr);
85095fce210SBarry Smith   for (i=0; i<nranks; i++) {
8515b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8525b0d146aSStefano Zampini 
853684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
854ffc4695bSBarry Smith       ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);
855684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
856ffc4695bSBarry Smith       ierr = MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]);CHKERRMPI(ierr);
857684a874aSStefano Zampini #else
858ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
859684a874aSStefano Zampini #endif
860684a874aSStefano Zampini     } else {
861ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
862684a874aSStefano Zampini     }
86395fce210SBarry Smith   }
86495fce210SBarry Smith   PetscFunctionReturn(0);
86595fce210SBarry Smith }
86695fce210SBarry Smith 
867ad227feaSJunchao Zhang PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
86895fce210SBarry Smith {
8695b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
87095fce210SBarry Smith   PetscErrorCode ierr;
87195fce210SBarry Smith   MPI_Win        win;
8724b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
87395fce210SBarry Smith 
87495fce210SBarry Smith   PetscFunctionBegin;
875684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
876ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
877684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
878684a874aSStefano Zampini     PetscInt           i,nranks;
879684a874aSStefano Zampini     const PetscMPIInt  *ranks;
880684a874aSStefano Zampini 
881684a874aSStefano Zampini     ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
882684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
883ffc4695bSBarry Smith       ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
884684a874aSStefano Zampini     }
885684a874aSStefano Zampini   }
8865b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
88795fce210SBarry Smith   PetscFunctionReturn(0);
88895fce210SBarry Smith }
88995fce210SBarry Smith 
890eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
89195fce210SBarry Smith {
89295fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
89395fce210SBarry Smith   PetscErrorCode     ierr;
89495fce210SBarry Smith   PetscInt           i,nranks;
89595fce210SBarry Smith   const PetscMPIInt  *ranks;
8965b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
89795fce210SBarry Smith   const MPI_Datatype *mine,*remote;
89895fce210SBarry Smith   MPI_Win            win;
89995fce210SBarry Smith 
90095fce210SBarry Smith   PetscFunctionBegin;
901dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
90295fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
90395fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
904684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
90595fce210SBarry Smith   for (i=0; i<nranks; i++) {
9065b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9075b0d146aSStefano Zampini 
908ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);}
909c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
910ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
91195fce210SBarry Smith   }
91295fce210SBarry Smith   PetscFunctionReturn(0);
91395fce210SBarry Smith }
91495fce210SBarry Smith 
91500816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
91695fce210SBarry Smith {
91795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
91895fce210SBarry Smith   PetscErrorCode ierr;
91995fce210SBarry Smith   MPI_Win        win;
9204b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
92195fce210SBarry Smith 
92295fce210SBarry Smith   PetscFunctionBegin;
923684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
924ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9255b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
92695fce210SBarry Smith   PetscFunctionReturn(0);
92795fce210SBarry Smith }
9285b0d146aSStefano Zampini 
929eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
93095fce210SBarry Smith {
93195fce210SBarry Smith   PetscErrorCode     ierr;
93295fce210SBarry Smith   PetscInt           i,nranks;
93395fce210SBarry Smith   const PetscMPIInt  *ranks;
93495fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9355b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
93695fce210SBarry Smith   MPI_Win            win;
9375b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9385b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9395b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9405b0d146aSStefano Zampini #endif
94195fce210SBarry Smith 
94295fce210SBarry Smith   PetscFunctionBegin;
943dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
94495fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
94595fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
9465b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9475b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9485b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9495b0d146aSStefano Zampini   oldf = w->flavor;
9505b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
951684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9525b0d146aSStefano Zampini #else
953684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9545b0d146aSStefano Zampini #endif
9555b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9565b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9575b0d146aSStefano Zampini 
9585b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
959ffc4695bSBarry Smith     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRMPI(ierr);
960ffc4695bSBarry Smith     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
961c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
962ffc4695bSBarry Smith     ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
9635b0d146aSStefano Zampini #else
964ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRMPI(ierr);}
965c2c9d402SJose E. Roman     ierr = MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
966ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
9675b0d146aSStefano Zampini #endif
9685b0d146aSStefano Zampini   }
9695b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9705b0d146aSStefano Zampini   w->flavor = oldf;
9715b0d146aSStefano Zampini #endif
97295fce210SBarry Smith   PetscFunctionReturn(0);
97395fce210SBarry Smith }
97495fce210SBarry Smith 
97500816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
97695fce210SBarry Smith {
97795fce210SBarry Smith   PetscErrorCode ierr;
97895fce210SBarry Smith   MPI_Win        win;
9795b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9805b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
9815b0d146aSStefano Zampini #endif
9824b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
98395fce210SBarry Smith 
98495fce210SBarry Smith   PetscFunctionBegin;
985684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
986ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9875b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9885b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
9895b0d146aSStefano Zampini #else
9905b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
9915b0d146aSStefano Zampini #endif
99295fce210SBarry Smith   PetscFunctionReturn(0);
99395fce210SBarry Smith }
99495fce210SBarry Smith 
995dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
99695fce210SBarry Smith {
99795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
99895fce210SBarry Smith   PetscErrorCode ierr;
99995fce210SBarry Smith 
100095fce210SBarry Smith   PetscFunctionBegin;
100195fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
100295fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
100395fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
100495fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
100595fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
100695fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1007ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
1008ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
100995fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
101095fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
101195fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
101295fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
101395fce210SBarry Smith 
1014b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
101595fce210SBarry Smith   sf->data  = (void*)w;
101695fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
10175b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
10185b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
101995fce210SBarry Smith 
1020bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1021bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
10225b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
10235b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
10245b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
10255b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
102695fce210SBarry Smith 
102795fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
102895fce210SBarry Smith   {
102995fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1030c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
103195fce210SBarry Smith     if (ackbug) {
1032955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
103395fce210SBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_LIB,"Open MPI is known to be buggy (https://svn.open-mpi.org/trac/ompi/ticket/1905 and 2656), use -acknowledge_ompi_onesided_bug to proceed");
103495fce210SBarry Smith   }
103595fce210SBarry Smith #endif
103695fce210SBarry Smith   PetscFunctionReturn(0);
103795fce210SBarry Smith }
1038