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 PetscSFDataLink link; 6995fce210SBarry Smith PetscInt i,nranks; 7095fce210SBarry Smith const PetscInt *roffset,*rmine,*rremote; 7195fce210SBarry Smith const PetscMPIInt *ranks; 7295fce210SBarry Smith 7395fce210SBarry Smith PetscFunctionBegin; 7495fce210SBarry Smith /* Look for types in cache */ 7595fce210SBarry Smith for (link=w->link; link; link=link->next) { 7695fce210SBarry Smith PetscBool match; 779566063dSJacob Faibussowitsch PetscCall(MPIPetsc_Type_compare(unit,link->unit,&match)); 7895fce210SBarry Smith if (match) { 7995fce210SBarry Smith *localtypes = link->mine; 8095fce210SBarry Smith *remotetypes = link->remote; 8195fce210SBarry Smith PetscFunctionReturn(0); 8295fce210SBarry Smith } 8395fce210SBarry Smith } 8495fce210SBarry Smith 8595fce210SBarry Smith /* Create new composite types for each send rank */ 869566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote)); 879566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_dup(unit,&link->unit)); 899566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nranks,&link->mine,nranks,&link->remote)); 9095fce210SBarry Smith for (i=0; i<nranks; i++) { 915b0d146aSStefano Zampini PetscInt rcount = roffset[i+1] - roffset[i]; 9295fce210SBarry Smith PetscMPIInt *rmine,*rremote; 9395fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES) 9495fce210SBarry Smith rmine = sf->rmine + sf->roffset[i]; 9595fce210SBarry Smith rremote = sf->rremote + sf->roffset[i]; 9695fce210SBarry Smith #else 9795fce210SBarry Smith PetscInt j; 989566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(rcount,&rmine,rcount,&rremote)); 9995fce210SBarry Smith for (j=0; j<rcount; j++) { 1009566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j)); 1019566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j)); 10295fce210SBarry Smith } 10395fce210SBarry Smith #endif 1045b0d146aSStefano Zampini 1059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i])); 1069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i])); 10795fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES) 1089566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine,rremote)); 10995fce210SBarry Smith #endif 1109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&link->mine[i])); 1119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&link->remote[i])); 11295fce210SBarry Smith } 11395fce210SBarry Smith link->next = w->link; 11495fce210SBarry Smith w->link = link; 11595fce210SBarry Smith 11695fce210SBarry Smith *localtypes = link->mine; 11795fce210SBarry Smith *remotetypes = link->remote; 11895fce210SBarry Smith PetscFunctionReturn(0); 11995fce210SBarry Smith } 12095fce210SBarry Smith 12195fce210SBarry Smith /*@C 1225b0d146aSStefano Zampini PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation 1235b0d146aSStefano Zampini 1245b0d146aSStefano Zampini Logically Collective 1255b0d146aSStefano Zampini 1264165533cSJose E. Roman Input Parameters: 1275b0d146aSStefano Zampini + sf - star forest for communication 1285b0d146aSStefano Zampini - flavor - flavor type 1295b0d146aSStefano Zampini 1305b0d146aSStefano Zampini Options Database Key: 1315b0d146aSStefano Zampini . -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType) 1325b0d146aSStefano Zampini 1335b0d146aSStefano Zampini Level: advanced 1345b0d146aSStefano Zampini 1355b0d146aSStefano Zampini Notes: Windows reusage follow this rules: 1365b0d146aSStefano Zampini 1375b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create 1385b0d146aSStefano Zampini 1395b0d146aSStefano 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. 1405b0d146aSStefano Zampini for i=1 to K 1415b0d146aSStefano Zampini PetscSFOperationBegin(rootdata1,leafdata_whatever); 1425b0d146aSStefano Zampini PetscSFOperationEnd(rootdata1,leafdata_whatever); 1435b0d146aSStefano Zampini ... 1445b0d146aSStefano Zampini PetscSFOperationBegin(rootdataN,leafdata_whatever); 1455b0d146aSStefano Zampini PetscSFOperationEnd(rootdataN,leafdata_whatever); 1465b0d146aSStefano Zampini endfor 1475b0d146aSStefano Zampini The following pattern will instead raise an error 1485b0d146aSStefano Zampini PetscSFOperationBegin(rootdata1,leafdata_whatever); 1495b0d146aSStefano Zampini PetscSFOperationEnd(rootdata1,leafdata_whatever); 1505b0d146aSStefano Zampini PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever); 1515b0d146aSStefano Zampini PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever); 1525b0d146aSStefano Zampini 1535b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use 1545b0d146aSStefano Zampini 1555b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE 1565b0d146aSStefano Zampini 1575b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType() 1585b0d146aSStefano Zampini @*/ 1595b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor) 1605b0d146aSStefano Zampini { 1615b0d146aSStefano Zampini PetscFunctionBegin; 1625b0d146aSStefano Zampini PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 1635b0d146aSStefano Zampini PetscValidLogicalCollectiveEnum(sf,flavor,2); 164*cac4c232SBarry Smith PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor)); 1655b0d146aSStefano Zampini PetscFunctionReturn(0); 1665b0d146aSStefano Zampini } 1675b0d146aSStefano Zampini 1685b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor) 1695b0d146aSStefano Zampini { 1705b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 1715b0d146aSStefano Zampini 1725b0d146aSStefano Zampini PetscFunctionBegin; 1735b0d146aSStefano Zampini w->flavor = flavor; 1745b0d146aSStefano Zampini PetscFunctionReturn(0); 1755b0d146aSStefano Zampini } 1765b0d146aSStefano Zampini 1775b0d146aSStefano Zampini /*@C 1785b0d146aSStefano Zampini PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication 1795b0d146aSStefano Zampini 1805b0d146aSStefano Zampini Logically Collective 1815b0d146aSStefano Zampini 1824165533cSJose E. Roman Input Parameter: 1835b0d146aSStefano Zampini . sf - star forest for communication 1845b0d146aSStefano Zampini 1854165533cSJose E. Roman Output Parameter: 1865b0d146aSStefano Zampini . flavor - flavor type 1875b0d146aSStefano Zampini 1885b0d146aSStefano Zampini Level: advanced 1895b0d146aSStefano Zampini 1905b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType() 1915b0d146aSStefano Zampini @*/ 1925b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor) 1935b0d146aSStefano Zampini { 1945b0d146aSStefano Zampini PetscFunctionBegin; 1955b0d146aSStefano Zampini PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 1965b0d146aSStefano Zampini PetscValidPointer(flavor,2); 197*cac4c232SBarry Smith PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor)); 1985b0d146aSStefano Zampini PetscFunctionReturn(0); 1995b0d146aSStefano Zampini } 2005b0d146aSStefano Zampini 2015b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor) 2025b0d146aSStefano Zampini { 2035b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 2045b0d146aSStefano Zampini 2055b0d146aSStefano Zampini PetscFunctionBegin; 2065b0d146aSStefano Zampini *flavor = w->flavor; 2075b0d146aSStefano Zampini PetscFunctionReturn(0); 2085b0d146aSStefano Zampini } 2095b0d146aSStefano Zampini 2105b0d146aSStefano Zampini /*@C 2115b0d146aSStefano Zampini PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication 21295fce210SBarry Smith 21395fce210SBarry Smith Logically Collective 21495fce210SBarry Smith 2154165533cSJose E. Roman Input Parameters: 21695fce210SBarry Smith + sf - star forest for communication 21795fce210SBarry Smith - sync - synchronization type 21895fce210SBarry Smith 21995fce210SBarry Smith Options Database Key: 22060263706SJed Brown . -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType) 22195fce210SBarry Smith 22295fce210SBarry Smith Level: advanced 22395fce210SBarry Smith 22495fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType() 22595fce210SBarry Smith @*/ 22695fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync) 22795fce210SBarry Smith { 22895fce210SBarry Smith PetscFunctionBegin; 22995fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 23095fce210SBarry Smith PetscValidLogicalCollectiveEnum(sf,sync,2); 231*cac4c232SBarry Smith PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync)); 23295fce210SBarry Smith PetscFunctionReturn(0); 23395fce210SBarry Smith } 23495fce210SBarry Smith 235f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync) 23695fce210SBarry Smith { 23795fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 23895fce210SBarry Smith 23995fce210SBarry Smith PetscFunctionBegin; 24095fce210SBarry Smith w->sync = sync; 24195fce210SBarry Smith PetscFunctionReturn(0); 24295fce210SBarry Smith } 24395fce210SBarry Smith 24495fce210SBarry Smith /*@C 2455b0d146aSStefano Zampini PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication 24695fce210SBarry Smith 24795fce210SBarry Smith Logically Collective 24895fce210SBarry Smith 2494165533cSJose E. Roman Input Parameter: 25095fce210SBarry Smith . sf - star forest for communication 25195fce210SBarry Smith 2524165533cSJose E. Roman Output Parameter: 25395fce210SBarry Smith . sync - synchronization type 25495fce210SBarry Smith 25595fce210SBarry Smith Level: advanced 25695fce210SBarry Smith 2575b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType() 25895fce210SBarry Smith @*/ 25995fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync) 26095fce210SBarry Smith { 26195fce210SBarry Smith PetscFunctionBegin; 26295fce210SBarry Smith PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 26395fce210SBarry Smith PetscValidPointer(sync,2); 264*cac4c232SBarry Smith PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync)); 26595fce210SBarry Smith PetscFunctionReturn(0); 26695fce210SBarry Smith } 26795fce210SBarry Smith 268f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync) 26995fce210SBarry Smith { 27095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 27195fce210SBarry Smith 27295fce210SBarry Smith PetscFunctionBegin; 27395fce210SBarry Smith *sync = w->sync; 27495fce210SBarry Smith PetscFunctionReturn(0); 27595fce210SBarry Smith } 27695fce210SBarry Smith 27795fce210SBarry Smith /*@C 2785b0d146aSStefano Zampini PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation 2795b0d146aSStefano Zampini 2805b0d146aSStefano Zampini Logically Collective 2815b0d146aSStefano Zampini 2824165533cSJose E. Roman Input Parameters: 2835b0d146aSStefano Zampini + sf - star forest for communication 2845b0d146aSStefano Zampini - info - MPI_Info handle 2855b0d146aSStefano Zampini 2865b0d146aSStefano Zampini Level: advanced 2875b0d146aSStefano Zampini 2885b0d146aSStefano Zampini Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL. 2895b0d146aSStefano Zampini 2905b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo() 2915b0d146aSStefano Zampini @*/ 2925b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info) 2935b0d146aSStefano Zampini { 2945b0d146aSStefano Zampini PetscFunctionBegin; 2955b0d146aSStefano Zampini PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 296*cac4c232SBarry Smith PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info)); 2975b0d146aSStefano Zampini PetscFunctionReturn(0); 2985b0d146aSStefano Zampini } 2995b0d146aSStefano Zampini 3005b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info) 3015b0d146aSStefano Zampini { 3025b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 3035b0d146aSStefano Zampini 3045b0d146aSStefano Zampini PetscFunctionBegin; 3055b0d146aSStefano Zampini if (w->info != MPI_INFO_NULL) { 3069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_free(&w->info)); 3075b0d146aSStefano Zampini } 3085b0d146aSStefano Zampini if (info != MPI_INFO_NULL) { 3099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_dup(info,&w->info)); 3105b0d146aSStefano Zampini } 3115b0d146aSStefano Zampini PetscFunctionReturn(0); 3125b0d146aSStefano Zampini } 3135b0d146aSStefano Zampini 3145b0d146aSStefano Zampini /*@C 3155b0d146aSStefano Zampini PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation 3165b0d146aSStefano Zampini 3175b0d146aSStefano Zampini Logically Collective 3185b0d146aSStefano Zampini 3194165533cSJose E. Roman Input Parameter: 3205b0d146aSStefano Zampini . sf - star forest for communication 3215b0d146aSStefano Zampini 3224165533cSJose E. Roman Output Parameter: 3235b0d146aSStefano Zampini . info - MPI_Info handle 3245b0d146aSStefano Zampini 3255b0d146aSStefano Zampini Level: advanced 3265b0d146aSStefano Zampini 3275b0d146aSStefano Zampini Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL 3285b0d146aSStefano Zampini 3295b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo() 3305b0d146aSStefano Zampini @*/ 3315b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info) 3325b0d146aSStefano Zampini { 3335b0d146aSStefano Zampini PetscFunctionBegin; 3345b0d146aSStefano Zampini PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 3355b0d146aSStefano Zampini PetscValidPointer(info,2); 336*cac4c232SBarry Smith PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info)); 3375b0d146aSStefano Zampini PetscFunctionReturn(0); 3385b0d146aSStefano Zampini } 3395b0d146aSStefano Zampini 3405b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info) 3415b0d146aSStefano Zampini { 3425b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 3435b0d146aSStefano Zampini 3445b0d146aSStefano Zampini PetscFunctionBegin; 3455b0d146aSStefano Zampini *info = w->info; 3465b0d146aSStefano Zampini PetscFunctionReturn(0); 3475b0d146aSStefano Zampini } 3485b0d146aSStefano Zampini 3495b0d146aSStefano Zampini /* 35095fce210SBarry Smith PetscSFGetWindow - Get a window for use with a given data type 35195fce210SBarry Smith 35295fce210SBarry Smith Collective on PetscSF 35395fce210SBarry Smith 3544165533cSJose E. Roman Input Parameters: 35595fce210SBarry Smith + sf - star forest 35695fce210SBarry Smith . unit - data type 35795fce210SBarry Smith . array - array to be sent 3585b0d146aSStefano Zampini . sync - type of synchronization PetscSFWindowSyncType 35995fce210SBarry Smith . epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window 3605b0d146aSStefano Zampini . fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE 3615b0d146aSStefano Zampini . postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE 362684a874aSStefano Zampini - startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE 36395fce210SBarry Smith 3644165533cSJose E. Roman Output Parameters: 365684a874aSStefano Zampini + target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only) 366684a874aSStefano Zampini + reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only) 367684a874aSStefano Zampini - win - window 36895fce210SBarry Smith 36995fce210SBarry Smith Level: developer 370dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes() 3715b0d146aSStefano Zampini */ 372684a874aSStefano 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) 37395fce210SBarry Smith { 37495fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 37595fce210SBarry Smith MPI_Aint lb,lb_true,bytes,bytes_true; 37695fce210SBarry Smith PetscSFWinLink link; 377d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 3785b0d146aSStefano Zampini MPI_Aint winaddr; 3795b0d146aSStefano Zampini PetscInt nranks; 380d547623eSJunchao Zhang #endif 3815b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE, update = PETSC_FALSE; 3825b0d146aSStefano Zampini PetscBool dummy[2]; 3835b0d146aSStefano Zampini MPI_Aint wsize; 38495fce210SBarry Smith 38595fce210SBarry Smith PetscFunctionBegin; 3869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_extent(unit,&lb,&bytes)); 3879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_true_extent(unit,&lb_true,&bytes_true)); 3882c71b3e2SJacob 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"); 3892c71b3e2SJacob 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"); 3905b0d146aSStefano Zampini if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 3915b0d146aSStefano Zampini for (link=w->wins; reuse && link; link=link->next) { 3925b0d146aSStefano Zampini PetscBool winok = PETSC_FALSE; 3935b0d146aSStefano Zampini if (w->flavor != link->flavor) continue; 3945b0d146aSStefano Zampini switch (w->flavor) { 3955b0d146aSStefano 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) */ 3965b0d146aSStefano Zampini if (array == link->addr) { 39776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3985b0d146aSStefano Zampini dummy[0] = PETSC_TRUE; 3995b0d146aSStefano Zampini dummy[1] = PETSC_TRUE; 4009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,dummy,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf))); 4019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf))); 4022c71b3e2SJacob 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"); 40376bd3646SJed Brown } 40428b400f6SJacob Faibussowitsch PetscCheck(!link->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use"); 4052c71b3e2SJacob Faibussowitsch PetscCheckFalse(epoch && link->epoch,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished"); 4065b0d146aSStefano Zampini winok = PETSC_TRUE; 4075b0d146aSStefano Zampini link->paddr = array; 40876bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 4095b0d146aSStefano Zampini dummy[0] = PETSC_FALSE; 4105b0d146aSStefano Zampini dummy[1] = PETSC_FALSE; 4119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,dummy ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf))); 4129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf))); 4132c71b3e2SJacob 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"); 4145b0d146aSStefano Zampini } 4155b0d146aSStefano Zampini break; 4165b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */ 4175b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 4185b0d146aSStefano Zampini if (!link->inuse && bytes == (MPI_Aint)link->bytes) { 4195b0d146aSStefano Zampini update = PETSC_TRUE; 4205b0d146aSStefano Zampini link->paddr = array; 4215b0d146aSStefano Zampini winok = PETSC_TRUE; 4225b0d146aSStefano Zampini } 4235b0d146aSStefano Zampini break; 42498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]); 4255b0d146aSStefano Zampini } 4265b0d146aSStefano Zampini if (winok) { 4275b0d146aSStefano Zampini *win = link->win; 4289566063dSJacob Faibussowitsch PetscCall(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))); 4295b0d146aSStefano Zampini goto found; 4305b0d146aSStefano Zampini } 4315b0d146aSStefano Zampini } 4325b0d146aSStefano Zampini 4335b0d146aSStefano Zampini wsize = (MPI_Aint)bytes*sf->nroots; 4349566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 43595fce210SBarry Smith link->bytes = bytes; 43695fce210SBarry Smith link->next = w->wins; 4375b0d146aSStefano Zampini link->flavor = w->flavor; 4385b0d146aSStefano Zampini link->dyn_target_addr = NULL; 439684a874aSStefano Zampini link->reqs = NULL; 44095fce210SBarry Smith w->wins = link; 441684a874aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 442684a874aSStefano Zampini PetscInt i; 443684a874aSStefano Zampini 4449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks,&link->reqs)); 445684a874aSStefano Zampini for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL; 446684a874aSStefano Zampini } 4475b0d146aSStefano Zampini switch (w->flavor) { 4485b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_CREATE: 4499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win)); 4505b0d146aSStefano Zampini link->addr = array; 4515b0d146aSStefano Zampini link->paddr = array; 4525b0d146aSStefano Zampini break; 453d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 4545b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_DYNAMIC: 4559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win)); 4565b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */ 457244dd087SJunchao Zhang PetscCallMPI(MPI_Win_attach(link->win,wsize ? array : (void*)dummy,wsize)); 4585b0d146aSStefano Zampini #else 4599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_attach(link->win,array,wsize)); 4605b0d146aSStefano Zampini #endif 4615b0d146aSStefano Zampini link->addr = array; 4625b0d146aSStefano Zampini link->paddr = array; 46328b400f6SJacob Faibussowitsch PetscCheck(w->dynsf,PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()"); 4649566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(w->dynsf)); 4659566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL)); 4669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks,&link->dyn_target_addr)); 4679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get_address(array,&winaddr)); 4689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE)); 4699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE)); 4705b0d146aSStefano Zampini break; 4715b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: 4729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win)); 4735b0d146aSStefano Zampini update = PETSC_TRUE; 4745b0d146aSStefano Zampini link->paddr = array; 4755b0d146aSStefano Zampini break; 476d547623eSJunchao Zhang #endif 4775b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 4785b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 4799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win)); 4805b0d146aSStefano Zampini update = PETSC_TRUE; 4815b0d146aSStefano Zampini link->paddr = array; 4825b0d146aSStefano Zampini break; 4835b0d146aSStefano Zampini #endif 48498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]); 4855b0d146aSStefano Zampini } 4869566063dSJacob Faibussowitsch PetscCall(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))); 48795fce210SBarry Smith *win = link->win; 48895fce210SBarry Smith 4895b0d146aSStefano Zampini found: 4905b0d146aSStefano Zampini 491684a874aSStefano Zampini if (target_disp) *target_disp = link->dyn_target_addr; 492684a874aSStefano Zampini if (reqs) *reqs = link->reqs; 493684a874aSStefano Zampini if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */ 494684a874aSStefano Zampini PetscMPIInt rank; 495684a874aSStefano Zampini 4969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank)); 4979566063dSJacob Faibussowitsch if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win)); 4989566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(link->addr,array,sf->nroots*bytes)); 4995b0d146aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 5009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(rank,*win)); 5019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(0,*win)); 5025b0d146aSStefano Zampini } 5035b0d146aSStefano Zampini } 5045b0d146aSStefano Zampini link->inuse = PETSC_TRUE; 5055b0d146aSStefano Zampini link->epoch = epoch; 50695fce210SBarry Smith if (epoch) { 5075b0d146aSStefano Zampini switch (sync) { 50895fce210SBarry Smith case PETSCSF_WINDOW_SYNC_FENCE: 5099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(fenceassert,*win)); 51095fce210SBarry Smith break; 51195fce210SBarry Smith case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ 51295fce210SBarry Smith break; 51395fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 51495fce210SBarry Smith MPI_Group ingroup,outgroup; 5155b0d146aSStefano Zampini PetscMPIInt isize,osize; 5165b0d146aSStefano Zampini 5175b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=vader does not like calling 5185b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 5195b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 5205b0d146aSStefano Zampini So, we do not even issue the corresponding start and post calls 5215b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 5225b0d146aSStefano Zampini start(outgroup) has a matching post(ingroup) 5235b0d146aSStefano Zampini and this is guaranteed by PetscSF 5245b0d146aSStefano Zampini */ 5259566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf,&ingroup,&outgroup)); 5269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup,&isize)); 5279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup,&osize)); 5289566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_post(ingroup,postassert,*win)); 5299566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_start(outgroup,startassert,*win)); 53095fce210SBarry Smith } break; 53195fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type"); 53295fce210SBarry Smith } 53395fce210SBarry Smith } 53495fce210SBarry Smith PetscFunctionReturn(0); 53595fce210SBarry Smith } 53695fce210SBarry Smith 5375b0d146aSStefano Zampini /* 53895fce210SBarry Smith PetscSFFindWindow - Finds a window that is already in use 53995fce210SBarry Smith 54095fce210SBarry Smith Not Collective 54195fce210SBarry Smith 5424165533cSJose E. Roman Input Parameters: 54395fce210SBarry Smith + sf - star forest 54495fce210SBarry Smith . unit - data type 54595fce210SBarry Smith - array - array with which the window is associated 54695fce210SBarry Smith 5474165533cSJose E. Roman Output Parameters: 548684a874aSStefano Zampini + win - window 549684a874aSStefano Zampini - reqs - outstanding requests associated to the window 55095fce210SBarry Smith 55195fce210SBarry Smith Level: developer 55295fce210SBarry Smith 55395fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow() 5545b0d146aSStefano Zampini */ 555684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs) 55695fce210SBarry Smith { 55795fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 55895fce210SBarry Smith PetscSFWinLink link; 55995fce210SBarry Smith 56095fce210SBarry Smith PetscFunctionBegin; 561c0cd0301SJed Brown *win = MPI_WIN_NULL; 56295fce210SBarry Smith for (link=w->wins; link; link=link->next) { 5635b0d146aSStefano Zampini if (array == link->paddr) { 5642abc8c78SJacob Faibussowitsch 5659566063dSJacob Faibussowitsch PetscCall(PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf))); 56695fce210SBarry Smith *win = link->win; 567684a874aSStefano Zampini *reqs = link->reqs; 56895fce210SBarry Smith PetscFunctionReturn(0); 56995fce210SBarry Smith } 57095fce210SBarry Smith } 57195fce210SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use"); 57295fce210SBarry Smith } 57395fce210SBarry Smith 5745b0d146aSStefano Zampini /* 57595fce210SBarry Smith PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow() 57695fce210SBarry Smith 57795fce210SBarry Smith Collective 57895fce210SBarry Smith 5794165533cSJose E. Roman Input Parameters: 58095fce210SBarry Smith + sf - star forest 58195fce210SBarry Smith . unit - data type 58295fce210SBarry Smith . array - array associated with window 5835b0d146aSStefano Zampini . sync - type of synchronization PetscSFWindowSyncType 58495fce210SBarry Smith . epoch - close an epoch, must match argument to PetscSFGetWindow() 5855b0d146aSStefano Zampini . update - if we have to update the local window array 58695fce210SBarry Smith - win - window 58795fce210SBarry Smith 58895fce210SBarry Smith Level: developer 58995fce210SBarry Smith 59095fce210SBarry Smith .seealso: PetscSFFindWindow() 5915b0d146aSStefano Zampini */ 5925b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win) 59395fce210SBarry Smith { 59495fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 59595fce210SBarry Smith PetscSFWinLink *p,link; 5965b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE; 5975b0d146aSStefano Zampini PetscSFWindowFlavorType flavor; 5985b0d146aSStefano Zampini void* laddr; 5995b0d146aSStefano Zampini size_t bytes; 60095fce210SBarry Smith 60195fce210SBarry Smith PetscFunctionBegin; 60295fce210SBarry Smith for (p=&w->wins; *p; p=&(*p)->next) { 60395fce210SBarry Smith link = *p; 60495fce210SBarry Smith if (*win == link->win) { 6052c71b3e2SJacob Faibussowitsch PetscCheckFalse(array != link->paddr,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array"); 60695fce210SBarry Smith if (epoch != link->epoch) { 60728b400f6SJacob Faibussowitsch PetscCheck(!epoch,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end"); 60895fce210SBarry Smith else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch"); 60995fce210SBarry Smith } 6105b0d146aSStefano Zampini laddr = link->addr; 6115b0d146aSStefano Zampini flavor = link->flavor; 6125b0d146aSStefano Zampini bytes = link->bytes; 6135b0d146aSStefano Zampini if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 6145b0d146aSStefano Zampini else { *p = link->next; update = PETSC_FALSE; } /* remove from list */ 61595fce210SBarry Smith goto found; 61695fce210SBarry Smith } 61795fce210SBarry Smith } 61895fce210SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use"); 61995fce210SBarry Smith 62095fce210SBarry Smith found: 6219566063dSJacob Faibussowitsch PetscCall(PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf))); 62295fce210SBarry Smith if (epoch) { 6235b0d146aSStefano Zampini switch (sync) { 62495fce210SBarry Smith case PETSCSF_WINDOW_SYNC_FENCE: 6259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(fenceassert,*win)); 62695fce210SBarry Smith break; 6275b0d146aSStefano Zampini case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ 6285b0d146aSStefano Zampini break; 62995fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 6305b0d146aSStefano Zampini MPI_Group ingroup,outgroup; 6315b0d146aSStefano Zampini PetscMPIInt isize,osize; 6325b0d146aSStefano Zampini 6335b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=wader does not like calling 6345b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 6355b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 6365b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 6375b0d146aSStefano Zampini - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete 6385b0d146aSStefano Zampini - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait 6395b0d146aSStefano Zampini */ 6409566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf,&ingroup,&outgroup)); 6419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup,&isize)); 6429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup,&osize)); 6439566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_complete(*win)); 6449566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_wait(*win)); 64595fce210SBarry Smith } break; 64695fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type"); 64795fce210SBarry Smith } 64895fce210SBarry Smith } 6495b0d146aSStefano Zampini if (update) { 6505b0d146aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 6519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win)); 6525b0d146aSStefano Zampini } 6539566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(array,laddr,sf->nroots*bytes)); 6545b0d146aSStefano Zampini } 6555b0d146aSStefano Zampini link->epoch = PETSC_FALSE; 6565b0d146aSStefano Zampini link->inuse = PETSC_FALSE; 6575b0d146aSStefano Zampini link->paddr = NULL; 6585b0d146aSStefano Zampini if (!reuse) { 6599566063dSJacob Faibussowitsch PetscCall(PetscFree(link->dyn_target_addr)); 6609566063dSJacob Faibussowitsch PetscCall(PetscFree(link->reqs)); 6619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&link->win)); 6629566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 66395fce210SBarry Smith *win = MPI_WIN_NULL; 6645b0d146aSStefano Zampini } 66595fce210SBarry Smith PetscFunctionReturn(0); 66695fce210SBarry Smith } 66795fce210SBarry Smith 66895fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf) 66995fce210SBarry Smith { 67095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 67195fce210SBarry Smith MPI_Group ingroup,outgroup; 67295fce210SBarry Smith 67395fce210SBarry Smith PetscFunctionBegin; 6749566063dSJacob Faibussowitsch PetscCall(PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY)); 6755b0d146aSStefano Zampini if (!w->dynsf) { 6765b0d146aSStefano Zampini PetscInt i; 6775b0d146aSStefano Zampini PetscSFNode *remotes; 6785b0d146aSStefano Zampini 6799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks,&remotes)); 6805b0d146aSStefano Zampini for (i=0;i<sf->nranks;i++) { 6815b0d146aSStefano Zampini remotes[i].rank = sf->ranks[i]; 6825b0d146aSStefano Zampini remotes[i].index = 0; 6835b0d146aSStefano Zampini } 6849566063dSJacob Faibussowitsch PetscCall(PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf)); 6859566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE)); /* break recursion */ 6869566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER)); 6879566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf)); 6885b0d146aSStefano Zampini } 68995fce210SBarry Smith switch (w->sync) { 69095fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: 6919566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf,&ingroup,&outgroup)); 69295fce210SBarry Smith default: 69395fce210SBarry Smith break; 69495fce210SBarry Smith } 69595fce210SBarry Smith PetscFunctionReturn(0); 69695fce210SBarry Smith } 69795fce210SBarry Smith 6984416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf) 69995fce210SBarry Smith { 70095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 7015b0d146aSStefano Zampini PetscSFWindowFlavorType flavor = w->flavor; 70295fce210SBarry Smith 70395fce210SBarry Smith PetscFunctionBegin; 7049566063dSJacob Faibussowitsch PetscCall(PetscOptionsHead(PetscOptionsObject,"PetscSF Window options")); 7059566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_sync","synchronization type to use for PetscSF Window communication","PetscSFWindowSetSyncType",PetscSFWindowSyncTypes,(PetscEnum)w->sync,(PetscEnum*)&w->sync,NULL)); 7069566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL)); 7079566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(sf,flavor)); 7089566063dSJacob Faibussowitsch PetscCall(PetscOptionsTail()); 70995fce210SBarry Smith PetscFunctionReturn(0); 71095fce210SBarry Smith } 71195fce210SBarry Smith 71295fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf) 71395fce210SBarry Smith { 71495fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 71595fce210SBarry Smith PetscSFDataLink link,next; 71695fce210SBarry Smith PetscSFWinLink wlink,wnext; 71795fce210SBarry Smith PetscInt i; 71895fce210SBarry Smith 71995fce210SBarry Smith PetscFunctionBegin; 72095fce210SBarry Smith for (link=w->link; link; link=next) { 72195fce210SBarry Smith next = link->next; 7229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->unit)); 72395fce210SBarry Smith for (i=0; i<sf->nranks; i++) { 7249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->mine[i])); 7259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->remote[i])); 72695fce210SBarry Smith } 7279566063dSJacob Faibussowitsch PetscCall(PetscFree2(link->mine,link->remote)); 7289566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 72995fce210SBarry Smith } 73095fce210SBarry Smith w->link = NULL; 73195fce210SBarry Smith for (wlink=w->wins; wlink; wlink=wnext) { 73295fce210SBarry Smith wnext = wlink->next; 73328b400f6SJacob Faibussowitsch PetscCheck(!wlink->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr); 7349566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->dyn_target_addr)); 7359566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->reqs)); 7369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&wlink->win)); 7379566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink)); 73895fce210SBarry Smith } 73995fce210SBarry Smith w->wins = NULL; 7409566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&w->dynsf)); 7415b0d146aSStefano Zampini if (w->info != MPI_INFO_NULL) { 7429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_free(&w->info)); 7435b0d146aSStefano Zampini } 74495fce210SBarry Smith PetscFunctionReturn(0); 74595fce210SBarry Smith } 74695fce210SBarry Smith 74795fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf) 74895fce210SBarry Smith { 74995fce210SBarry Smith PetscFunctionBegin; 7509566063dSJacob Faibussowitsch PetscCall(PetscSFReset_Window(sf)); 7519566063dSJacob Faibussowitsch PetscCall(PetscFree(sf->data)); 7529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL)); 7539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL)); 7549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL)); 7559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL)); 7569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL)); 7579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL)); 75895fce210SBarry Smith PetscFunctionReturn(0); 75995fce210SBarry Smith } 76095fce210SBarry Smith 76195fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer) 76295fce210SBarry Smith { 76395fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 76495fce210SBarry Smith PetscBool iascii; 7655b0d146aSStefano Zampini PetscViewerFormat format; 76695fce210SBarry Smith 76795fce210SBarry Smith PetscFunctionBegin; 7689566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 7699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 77095fce210SBarry Smith if (iascii) { 7719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," current flavor=%s synchronization=%s MultiSF sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered")); 7725b0d146aSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 7735b0d146aSStefano Zampini if (w->info != MPI_INFO_NULL) { 7745b0d146aSStefano Zampini PetscMPIInt k,nkeys; 7755b0d146aSStefano Zampini char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL]; 7765b0d146aSStefano Zampini 7779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nkeys(w->info,&nkeys)); 7789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," current info with %d keys. Ordered key-value pairs follow:\n",nkeys)); 7795b0d146aSStefano Zampini for (k = 0; k < nkeys; k++) { 7805b0d146aSStefano Zampini PetscMPIInt flag; 7815b0d146aSStefano Zampini 7829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nthkey(w->info,k,key)); 7839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag)); 78428b400f6SJacob Faibussowitsch PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key); 7859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," %s = %s\n",key,value)); 7865b0d146aSStefano Zampini } 7875b0d146aSStefano Zampini } else { 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," current info=MPI_INFO_NULL\n")); 7895b0d146aSStefano Zampini } 7905b0d146aSStefano Zampini } 79195fce210SBarry Smith } 79295fce210SBarry Smith PetscFunctionReturn(0); 79395fce210SBarry Smith } 79495fce210SBarry Smith 79595fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf) 79695fce210SBarry Smith { 79795fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 79895fce210SBarry Smith PetscSFWindowSyncType synctype; 79995fce210SBarry Smith 80095fce210SBarry Smith PetscFunctionBegin; 80195fce210SBarry Smith synctype = w->sync; 80295fce210SBarry Smith /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */ 8035b0d146aSStefano Zampini if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK; 8049566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetSyncType(newsf,synctype)); 8059566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(newsf,w->flavor)); 8069566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetInfo(newsf,w->info)); 80795fce210SBarry Smith PetscFunctionReturn(0); 80895fce210SBarry Smith } 80995fce210SBarry Smith 810ad227feaSJunchao Zhang static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op) 81195fce210SBarry Smith { 81295fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 81395fce210SBarry Smith PetscInt i,nranks; 81495fce210SBarry Smith const PetscMPIInt *ranks; 8155b0d146aSStefano Zampini const MPI_Aint *target_disp; 81695fce210SBarry Smith const MPI_Datatype *mine,*remote; 817684a874aSStefano Zampini MPI_Request *reqs; 81895fce210SBarry Smith MPI_Win win; 81995fce210SBarry Smith 82095fce210SBarry Smith PetscFunctionBegin; 8212c71b3e2SJacob Faibussowitsch PetscCheckFalse(op != MPI_REPLACE,PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented"); 8229566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL)); 8239566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote)); 8249566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&reqs,&win)); 82595fce210SBarry Smith for (i=0; i<nranks; i++) { 8265b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 8275b0d146aSStefano Zampini 828684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 8299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win)); 830684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET) 8319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i])); 832684a874aSStefano Zampini #else 8339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win)); 834684a874aSStefano Zampini #endif 835684a874aSStefano Zampini } else { 8369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win)); 837684a874aSStefano Zampini } 83895fce210SBarry Smith } 83995fce210SBarry Smith PetscFunctionReturn(0); 84095fce210SBarry Smith } 84195fce210SBarry Smith 842ad227feaSJunchao Zhang PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op) 84395fce210SBarry Smith { 8445b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 84595fce210SBarry Smith MPI_Win win; 8464b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 84795fce210SBarry Smith 84895fce210SBarry Smith PetscFunctionBegin; 8499566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs)); 8509566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE)); 851684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 852684a874aSStefano Zampini PetscInt i,nranks; 853684a874aSStefano Zampini const PetscMPIInt *ranks; 854684a874aSStefano Zampini 8559566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL)); 856684a874aSStefano Zampini for (i=0; i<nranks; i++) { 8579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(ranks[i],win)); 858684a874aSStefano Zampini } 859684a874aSStefano Zampini } 8609566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win)); 86195fce210SBarry Smith PetscFunctionReturn(0); 86295fce210SBarry Smith } 86395fce210SBarry Smith 864eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op) 86595fce210SBarry Smith { 86695fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 86795fce210SBarry Smith PetscInt i,nranks; 86895fce210SBarry Smith const PetscMPIInt *ranks; 8695b0d146aSStefano Zampini const MPI_Aint *target_disp; 87095fce210SBarry Smith const MPI_Datatype *mine,*remote; 87195fce210SBarry Smith MPI_Win win; 87295fce210SBarry Smith 87395fce210SBarry Smith PetscFunctionBegin; 8749566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL)); 8759566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote)); 8769566063dSJacob Faibussowitsch PetscCall(PetscSFWindowOpTranslate(&op)); 8779566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win)); 87895fce210SBarry Smith for (i=0; i<nranks; i++) { 8795b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 8805b0d146aSStefano Zampini 8819566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win)); 8829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win)); 8839566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i],win)); 88495fce210SBarry Smith } 88595fce210SBarry Smith PetscFunctionReturn(0); 88695fce210SBarry Smith } 88795fce210SBarry Smith 88800816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op) 88995fce210SBarry Smith { 89095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 89195fce210SBarry Smith MPI_Win win; 8924b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 89395fce210SBarry Smith 89495fce210SBarry Smith PetscFunctionBegin; 8959566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs)); 8969566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE)); 8979566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win)); 89895fce210SBarry Smith PetscFunctionReturn(0); 89995fce210SBarry Smith } 9005b0d146aSStefano Zampini 901eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op) 90295fce210SBarry Smith { 90395fce210SBarry Smith PetscInt i,nranks; 90495fce210SBarry Smith const PetscMPIInt *ranks; 90595fce210SBarry Smith const MPI_Datatype *mine,*remote; 9065b0d146aSStefano Zampini const MPI_Aint *target_disp; 90795fce210SBarry Smith MPI_Win win; 9085b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 9095b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9105b0d146aSStefano Zampini PetscSFWindowFlavorType oldf; 9115b0d146aSStefano Zampini #endif 91295fce210SBarry Smith 91395fce210SBarry Smith PetscFunctionBegin; 9149566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL)); 9159566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote)); 9169566063dSJacob Faibussowitsch PetscCall(PetscSFWindowOpTranslate(&op)); 9175b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9185b0d146aSStefano Zampini /* FetchAndOp without MPI_Get_Accumulate requires locking. 9195b0d146aSStefano Zampini we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */ 9205b0d146aSStefano Zampini oldf = w->flavor; 9215b0d146aSStefano Zampini w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE; 9229566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win)); 9235b0d146aSStefano Zampini #else 9249566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win)); 9255b0d146aSStefano Zampini #endif 9265b0d146aSStefano Zampini for (i=0; i<nranks; i++) { 9275b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 9285b0d146aSStefano Zampini 9295b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win)); 9319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win)); 9329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win)); 9339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(ranks[i],win)); 9345b0d146aSStefano Zampini #else 9359566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win)); 9369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win)); 9379566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i],win)); 9385b0d146aSStefano Zampini #endif 9395b0d146aSStefano Zampini } 9405b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9415b0d146aSStefano Zampini w->flavor = oldf; 9425b0d146aSStefano Zampini #endif 94395fce210SBarry Smith PetscFunctionReturn(0); 94495fce210SBarry Smith } 94595fce210SBarry Smith 94600816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op) 94795fce210SBarry Smith { 94895fce210SBarry Smith MPI_Win win; 9495b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9505b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window*)sf->data; 9515b0d146aSStefano Zampini #endif 9524b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 95395fce210SBarry Smith 95495fce210SBarry Smith PetscFunctionBegin; 9559566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs)); 9569566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE)); 9575b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9589566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win)); 9595b0d146aSStefano Zampini #else 9609566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win)); 9615b0d146aSStefano Zampini #endif 96295fce210SBarry Smith PetscFunctionReturn(0); 96395fce210SBarry Smith } 96495fce210SBarry Smith 965dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf) 96695fce210SBarry Smith { 96795fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window*)sf->data; 96895fce210SBarry Smith 96995fce210SBarry Smith PetscFunctionBegin; 97095fce210SBarry Smith sf->ops->SetUp = PetscSFSetUp_Window; 97195fce210SBarry Smith sf->ops->SetFromOptions = PetscSFSetFromOptions_Window; 97295fce210SBarry Smith sf->ops->Reset = PetscSFReset_Window; 97395fce210SBarry Smith sf->ops->Destroy = PetscSFDestroy_Window; 97495fce210SBarry Smith sf->ops->View = PetscSFView_Window; 97595fce210SBarry Smith sf->ops->Duplicate = PetscSFDuplicate_Window; 976ad227feaSJunchao Zhang sf->ops->BcastBegin = PetscSFBcastBegin_Window; 977ad227feaSJunchao Zhang sf->ops->BcastEnd = PetscSFBcastEnd_Window; 97895fce210SBarry Smith sf->ops->ReduceBegin = PetscSFReduceBegin_Window; 97995fce210SBarry Smith sf->ops->ReduceEnd = PetscSFReduceEnd_Window; 98095fce210SBarry Smith sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window; 98195fce210SBarry Smith sf->ops->FetchAndOpEnd = PetscSFFetchAndOpEnd_Window; 98295fce210SBarry Smith 9839566063dSJacob Faibussowitsch PetscCall(PetscNewLog(sf,&w)); 98495fce210SBarry Smith sf->data = (void*)w; 98595fce210SBarry Smith w->sync = PETSCSF_WINDOW_SYNC_FENCE; 9865b0d146aSStefano Zampini w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE; 9875b0d146aSStefano Zampini w->info = MPI_INFO_NULL; 98895fce210SBarry Smith 9899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window)); 9909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window)); 9919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window)); 9929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window)); 9939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window)); 9949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window)); 99595fce210SBarry Smith 99695fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6)) 99795fce210SBarry Smith { 99895fce210SBarry Smith PetscBool ackbug = PETSC_FALSE; 9999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL)); 100095fce210SBarry Smith if (ackbug) { 10019566063dSJacob Faibussowitsch PetscCall(PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n")); 100295fce210SBarry 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"); 100395fce210SBarry Smith } 100495fce210SBarry Smith #endif 100595fce210SBarry Smith PetscFunctionReturn(0); 100695fce210SBarry Smith } 1007