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) */ 39d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op) 40d71ae5a4SJacob Faibussowitsch { 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: 54cab54364SBarry Smith + sf - star forest of type `PETSCSFWINDOW` 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 63cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetGraph()`, `PetscSFView()` 6495fce210SBarry Smith @*/ 65d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf, MPI_Datatype unit, const MPI_Datatype **localtypes, const MPI_Datatype **remotetypes) 66d71ae5a4SJacob Faibussowitsch { 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 122cab54364SBarry Smith PetscSFWindowSetFlavorType - Set flavor type for `MPI_Win` creation 1235b0d146aSStefano Zampini 1245b0d146aSStefano Zampini Logically Collective 1255b0d146aSStefano Zampini 1264165533cSJose E. Roman Input Parameters: 127cab54364SBarry Smith + sf - star forest for communication of type `PETSCSFWINDOW` 1285b0d146aSStefano Zampini - flavor - flavor type 1295b0d146aSStefano Zampini 1305b0d146aSStefano Zampini Options Database Key: 131cab54364SBarry Smith . -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see `PetscSFWindowFlavorType`) 1325b0d146aSStefano Zampini 1335b0d146aSStefano Zampini Level: advanced 1345b0d146aSStefano Zampini 135cab54364SBarry Smith Notes: 136cab54364SBarry Smith Windows reuse follows these rules: 137cab54364SBarry Smith .vb 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 157cab54364SBarry Smith .ve 1585b0d146aSStefano Zampini 159cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetFlavorType()` 1605b0d146aSStefano Zampini @*/ 161d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf, PetscSFWindowFlavorType flavor) 162d71ae5a4SJacob Faibussowitsch { 1635b0d146aSStefano Zampini PetscFunctionBegin; 1645b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 1655b0d146aSStefano Zampini PetscValidLogicalCollectiveEnum(sf, flavor, 2); 166cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetFlavorType_C", (PetscSF, PetscSFWindowFlavorType), (sf, flavor)); 1675b0d146aSStefano Zampini PetscFunctionReturn(0); 1685b0d146aSStefano Zampini } 1695b0d146aSStefano Zampini 170d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType flavor) 171d71ae5a4SJacob Faibussowitsch { 1725b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 1735b0d146aSStefano Zampini 1745b0d146aSStefano Zampini PetscFunctionBegin; 1755b0d146aSStefano Zampini w->flavor = flavor; 1765b0d146aSStefano Zampini PetscFunctionReturn(0); 1775b0d146aSStefano Zampini } 1785b0d146aSStefano Zampini 1795b0d146aSStefano Zampini /*@C 180cab54364SBarry Smith PetscSFWindowGetFlavorType - Get `PETSCSFWINDOW` flavor type for `PetscSF` communication 1815b0d146aSStefano Zampini 1825b0d146aSStefano Zampini Logically Collective 1835b0d146aSStefano Zampini 1844165533cSJose E. Roman Input Parameter: 185cab54364SBarry Smith . sf - star forest for communication of type `PETSCSFWINDOW` 1865b0d146aSStefano Zampini 1874165533cSJose E. Roman Output Parameter: 1885b0d146aSStefano Zampini . flavor - flavor type 1895b0d146aSStefano Zampini 1905b0d146aSStefano Zampini Level: advanced 1915b0d146aSStefano Zampini 192cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetFlavorType()` 1935b0d146aSStefano Zampini @*/ 194d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf, PetscSFWindowFlavorType *flavor) 195d71ae5a4SJacob Faibussowitsch { 1965b0d146aSStefano Zampini PetscFunctionBegin; 1975b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 1985b0d146aSStefano Zampini PetscValidPointer(flavor, 2); 199cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetFlavorType_C", (PetscSF, PetscSFWindowFlavorType *), (sf, flavor)); 2005b0d146aSStefano Zampini PetscFunctionReturn(0); 2015b0d146aSStefano Zampini } 2025b0d146aSStefano Zampini 203d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType *flavor) 204d71ae5a4SJacob Faibussowitsch { 2055b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 2065b0d146aSStefano Zampini 2075b0d146aSStefano Zampini PetscFunctionBegin; 2085b0d146aSStefano Zampini *flavor = w->flavor; 2095b0d146aSStefano Zampini PetscFunctionReturn(0); 2105b0d146aSStefano Zampini } 2115b0d146aSStefano Zampini 2125b0d146aSStefano Zampini /*@C 213cab54364SBarry Smith PetscSFWindowSetSyncType - Set synchronization type for `PetscSF` communication of type `PETSCSFWINDOW` 21495fce210SBarry Smith 21595fce210SBarry Smith Logically Collective 21695fce210SBarry Smith 2174165533cSJose E. Roman Input Parameters: 21895fce210SBarry Smith + sf - star forest for communication 21995fce210SBarry Smith - sync - synchronization type 22095fce210SBarry Smith 22195fce210SBarry Smith Options Database Key: 222cab54364SBarry Smith . -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see `PetscSFWindowSyncType`) 22395fce210SBarry Smith 22495fce210SBarry Smith Level: advanced 22595fce210SBarry Smith 226cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetSyncType()`, `PetscSFWindowSyncType` 22795fce210SBarry Smith @*/ 228d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf, PetscSFWindowSyncType sync) 229d71ae5a4SJacob Faibussowitsch { 23095fce210SBarry Smith PetscFunctionBegin; 23195fce210SBarry Smith PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 23295fce210SBarry Smith PetscValidLogicalCollectiveEnum(sf, sync, 2); 233cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetSyncType_C", (PetscSF, PetscSFWindowSyncType), (sf, sync)); 23495fce210SBarry Smith PetscFunctionReturn(0); 23595fce210SBarry Smith } 23695fce210SBarry Smith 237d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf, PetscSFWindowSyncType sync) 238d71ae5a4SJacob Faibussowitsch { 23995fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 24095fce210SBarry Smith 24195fce210SBarry Smith PetscFunctionBegin; 24295fce210SBarry Smith w->sync = sync; 24395fce210SBarry Smith PetscFunctionReturn(0); 24495fce210SBarry Smith } 24595fce210SBarry Smith 24695fce210SBarry Smith /*@C 247cab54364SBarry Smith PetscSFWindowGetSyncType - Get synchronization type for `PetscSF` communication of type `PETSCSFWINDOW` 24895fce210SBarry Smith 24995fce210SBarry Smith Logically Collective 25095fce210SBarry Smith 2514165533cSJose E. Roman Input Parameter: 25295fce210SBarry Smith . sf - star forest for communication 25395fce210SBarry Smith 2544165533cSJose E. Roman Output Parameter: 25595fce210SBarry Smith . sync - synchronization type 25695fce210SBarry Smith 25795fce210SBarry Smith Level: advanced 25895fce210SBarry Smith 259cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetSyncType()`, `PetscSFWindowSyncType` 26095fce210SBarry Smith @*/ 261d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf, PetscSFWindowSyncType *sync) 262d71ae5a4SJacob Faibussowitsch { 26395fce210SBarry Smith PetscFunctionBegin; 26495fce210SBarry Smith PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 26595fce210SBarry Smith PetscValidPointer(sync, 2); 266cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetSyncType_C", (PetscSF, PetscSFWindowSyncType *), (sf, sync)); 26795fce210SBarry Smith PetscFunctionReturn(0); 26895fce210SBarry Smith } 26995fce210SBarry Smith 270d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf, PetscSFWindowSyncType *sync) 271d71ae5a4SJacob Faibussowitsch { 27295fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 27395fce210SBarry Smith 27495fce210SBarry Smith PetscFunctionBegin; 27595fce210SBarry Smith *sync = w->sync; 27695fce210SBarry Smith PetscFunctionReturn(0); 27795fce210SBarry Smith } 27895fce210SBarry Smith 27995fce210SBarry Smith /*@C 280cab54364SBarry Smith PetscSFWindowSetInfo - Set the `MPI_Info` handle that will be used for subsequent windows allocation 2815b0d146aSStefano Zampini 2825b0d146aSStefano Zampini Logically Collective 2835b0d146aSStefano Zampini 2844165533cSJose E. Roman Input Parameters: 2855b0d146aSStefano Zampini + sf - star forest for communication 286cab54364SBarry Smith - info - `MPI_Info` handle 2875b0d146aSStefano Zampini 2885b0d146aSStefano Zampini Level: advanced 2895b0d146aSStefano Zampini 290cab54364SBarry Smith Note: 291cab54364SBarry Smith The info handle is duplicated with a call to `MPI_Info_dup()` unless info = `MPI_INFO_NULL`. 2925b0d146aSStefano Zampini 293cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetInfo()` 2945b0d146aSStefano Zampini @*/ 295d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetInfo(PetscSF sf, MPI_Info info) 296d71ae5a4SJacob Faibussowitsch { 2975b0d146aSStefano Zampini PetscFunctionBegin; 2985b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 299cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetInfo_C", (PetscSF, MPI_Info), (sf, info)); 3005b0d146aSStefano Zampini PetscFunctionReturn(0); 3015b0d146aSStefano Zampini } 3025b0d146aSStefano Zampini 303d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf, MPI_Info info) 304d71ae5a4SJacob Faibussowitsch { 3055b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 3065b0d146aSStefano Zampini 3075b0d146aSStefano Zampini PetscFunctionBegin; 30848a46eb9SPierre Jolivet if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info)); 30948a46eb9SPierre Jolivet if (info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_dup(info, &w->info)); 3105b0d146aSStefano Zampini PetscFunctionReturn(0); 3115b0d146aSStefano Zampini } 3125b0d146aSStefano Zampini 3135b0d146aSStefano Zampini /*@C 314cab54364SBarry Smith PetscSFWindowGetInfo - Get the `MPI_Info` handle used for windows allocation 3155b0d146aSStefano Zampini 3165b0d146aSStefano Zampini Logically Collective 3175b0d146aSStefano Zampini 3184165533cSJose E. Roman Input Parameter: 3195b0d146aSStefano Zampini . sf - star forest for communication 3205b0d146aSStefano Zampini 3214165533cSJose E. Roman Output Parameter: 322cab54364SBarry Smith . info - `MPI_Info` handle 3235b0d146aSStefano Zampini 3245b0d146aSStefano Zampini Level: advanced 3255b0d146aSStefano Zampini 326cab54364SBarry Smith Note: 327cab54364SBarry Smith If `PetscSFWindowSetInfo()` has not be called, this returns `MPI_INFO_NULL` 3285b0d146aSStefano Zampini 329cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetInfo()` 3305b0d146aSStefano Zampini @*/ 331d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetInfo(PetscSF sf, MPI_Info *info) 332d71ae5a4SJacob Faibussowitsch { 3335b0d146aSStefano Zampini PetscFunctionBegin; 3345b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3355b0d146aSStefano Zampini PetscValidPointer(info, 2); 336cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetInfo_C", (PetscSF, MPI_Info *), (sf, info)); 3375b0d146aSStefano Zampini PetscFunctionReturn(0); 3385b0d146aSStefano Zampini } 3395b0d146aSStefano Zampini 340d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf, MPI_Info *info) 341d71ae5a4SJacob Faibussowitsch { 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 352c3339decSBarry Smith Collective 35395fce210SBarry Smith 3544165533cSJose E. Roman Input Parameters: 35595fce210SBarry Smith + sf - star forest 35695fce210SBarry Smith . unit - data type 35795fce210SBarry Smith . array - array to be sent 358cab54364SBarry Smith . sync - type of synchronization `PetscSFWindowSyncType` 359cab54364SBarry Smith . epoch - `PETSC_TRUE` to acquire the window and start an epoch, `PETSC_FALSE` to just acquire the window 360cab54364SBarry Smith . fenceassert - assert parameter for call to `MPI_Win_fence()`, if sync == `PETSCSF_WINDOW_SYNC_FENCE` 361cab54364SBarry Smith . postassert - assert parameter for call to `MPI_Win_post()`, if sync == `PETSCSF_WINDOW_SYNC_ACTIVE` 362cab54364SBarry Smith - startassert - assert parameter for call to `MPI_Win_start()`, if sync == `PETSCSF_WINDOW_SYNC_ACTIVE` 36395fce210SBarry Smith 3644165533cSJose E. Roman Output Parameters: 365cab54364SBarry Smith + target_disp - target_disp argument for RMA calls (significative for `PETSCSF_WINDOW_FLAVOR_DYNAMIC` only) 366cab54364SBarry Smith + reqs - array of requests (significative for sync == `PETSCSF_WINDOW_SYNC_LOCK` only) 367684a874aSStefano Zampini - win - window 36895fce210SBarry Smith 36995fce210SBarry Smith Level: developer 370cab54364SBarry Smith 371cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFGetRootRanks()`, `PetscSFWindowGetDataTypes()` 3725b0d146aSStefano Zampini */ 373d71ae5a4SJacob Faibussowitsch 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) 374d71ae5a4SJacob Faibussowitsch { 37595fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 37695fce210SBarry Smith MPI_Aint lb, lb_true, bytes, bytes_true; 37795fce210SBarry Smith PetscSFWinLink link; 378d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 3795b0d146aSStefano Zampini MPI_Aint winaddr; 3805b0d146aSStefano Zampini PetscInt nranks; 381d547623eSJunchao Zhang #endif 3825b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE, update = PETSC_FALSE; 3835b0d146aSStefano Zampini PetscBool dummy[2]; 3845b0d146aSStefano Zampini MPI_Aint wsize; 38595fce210SBarry Smith 38695fce210SBarry Smith PetscFunctionBegin; 3879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_extent(unit, &lb, &bytes)); 3889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_true_extent(unit, &lb_true, &bytes_true)); 389c9cc58a2SBarry Smith PetscCheck(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"); 39008401ef6SPierre Jolivet PetscCheck(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"); 3915b0d146aSStefano Zampini if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 3925b0d146aSStefano Zampini for (link = w->wins; reuse && link; link = link->next) { 3935b0d146aSStefano Zampini PetscBool winok = PETSC_FALSE; 3945b0d146aSStefano Zampini if (w->flavor != link->flavor) continue; 3955b0d146aSStefano Zampini switch (w->flavor) { 3965b0d146aSStefano 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) */ 3975b0d146aSStefano Zampini if (array == link->addr) { 39876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3995b0d146aSStefano Zampini dummy[0] = PETSC_TRUE; 4005b0d146aSStefano Zampini dummy[1] = PETSC_TRUE; 4019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf))); 4029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf))); 40308401ef6SPierre Jolivet PetscCheck(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"); 40476bd3646SJed Brown } 40528b400f6SJacob Faibussowitsch PetscCheck(!link->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window in use"); 40608401ef6SPierre Jolivet PetscCheck(!epoch || !link->epoch, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window epoch not finished"); 4075b0d146aSStefano Zampini winok = PETSC_TRUE; 4085b0d146aSStefano Zampini link->paddr = array; 40976bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 4105b0d146aSStefano Zampini dummy[0] = PETSC_FALSE; 4115b0d146aSStefano Zampini dummy[1] = PETSC_FALSE; 4129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf))); 4139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf))); 41408401ef6SPierre Jolivet PetscCheck(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"); 4155b0d146aSStefano Zampini } 4165b0d146aSStefano Zampini break; 4175b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */ 4185b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 4195b0d146aSStefano Zampini if (!link->inuse && bytes == (MPI_Aint)link->bytes) { 4205b0d146aSStefano Zampini update = PETSC_TRUE; 4215b0d146aSStefano Zampini link->paddr = array; 4225b0d146aSStefano Zampini winok = PETSC_TRUE; 4235b0d146aSStefano Zampini } 4245b0d146aSStefano Zampini break; 425d71ae5a4SJacob Faibussowitsch default: 426d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]); 4275b0d146aSStefano Zampini } 4285b0d146aSStefano Zampini if (winok) { 4295b0d146aSStefano Zampini *win = link->win; 430*fef353a4SJacob Faibussowitsch PetscCall(PetscInfo(sf, "Reusing window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)PetscObjectComm((PetscObject)sf))); 4315b0d146aSStefano Zampini goto found; 4325b0d146aSStefano Zampini } 4335b0d146aSStefano Zampini } 4345b0d146aSStefano Zampini 4355b0d146aSStefano Zampini wsize = (MPI_Aint)bytes * sf->nroots; 4369566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 43795fce210SBarry Smith link->bytes = bytes; 43895fce210SBarry Smith link->next = w->wins; 4395b0d146aSStefano Zampini link->flavor = w->flavor; 4405b0d146aSStefano Zampini link->dyn_target_addr = NULL; 441684a874aSStefano Zampini link->reqs = NULL; 44295fce210SBarry Smith w->wins = link; 443684a874aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 444684a874aSStefano Zampini PetscInt i; 445684a874aSStefano Zampini 4469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks, &link->reqs)); 447684a874aSStefano Zampini for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL; 448684a874aSStefano Zampini } 4495b0d146aSStefano Zampini switch (w->flavor) { 4505b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_CREATE: 4519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_create(array, wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->win)); 4525b0d146aSStefano Zampini link->addr = array; 4535b0d146aSStefano Zampini link->paddr = array; 4545b0d146aSStefano Zampini break; 455d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 456d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_FLAVOR_DYNAMIC: 457d71ae5a4SJacob Faibussowitsch PetscCallMPI(MPI_Win_create_dynamic(w->info, PetscObjectComm((PetscObject)sf), &link->win)); 4585b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */ 459244dd087SJunchao Zhang PetscCallMPI(MPI_Win_attach(link->win, wsize ? array : (void *)dummy, wsize)); 4605b0d146aSStefano Zampini #else 4619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_attach(link->win, array, wsize)); 4625b0d146aSStefano Zampini #endif 4635b0d146aSStefano Zampini link->addr = array; 4645b0d146aSStefano Zampini link->paddr = array; 46528b400f6SJacob Faibussowitsch PetscCheck(w->dynsf, PetscObjectComm((PetscObject)sf), PETSC_ERR_ORDER, "Must call PetscSFSetUp()"); 4669566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(w->dynsf)); 4679566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(w->dynsf, &nranks, NULL, NULL, NULL, NULL)); 4689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &link->dyn_target_addr)); 4699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get_address(array, &winaddr)); 4709566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE)); 4719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE)); 4725b0d146aSStefano Zampini break; 4735b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: 4749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win)); 4755b0d146aSStefano Zampini update = PETSC_TRUE; 4765b0d146aSStefano Zampini link->paddr = array; 4775b0d146aSStefano Zampini break; 478d547623eSJunchao Zhang #endif 4795b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 4805b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 4819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate_shared(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win)); 4825b0d146aSStefano Zampini update = PETSC_TRUE; 4835b0d146aSStefano Zampini link->paddr = array; 4845b0d146aSStefano Zampini break; 4855b0d146aSStefano Zampini #endif 486d71ae5a4SJacob Faibussowitsch default: 487d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]); 4885b0d146aSStefano Zampini } 489*fef353a4SJacob Faibussowitsch PetscCall(PetscInfo(sf, "New window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)PetscObjectComm((PetscObject)sf))); 49095fce210SBarry Smith *win = link->win; 49195fce210SBarry Smith 4925b0d146aSStefano Zampini found: 4935b0d146aSStefano Zampini 494684a874aSStefano Zampini if (target_disp) *target_disp = link->dyn_target_addr; 495684a874aSStefano Zampini if (reqs) *reqs = link->reqs; 496684a874aSStefano Zampini if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */ 497684a874aSStefano Zampini PetscMPIInt rank; 498684a874aSStefano Zampini 4999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sf), &rank)); 5009566063dSJacob Faibussowitsch if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, MPI_MODE_NOCHECK, *win)); 5019566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(link->addr, array, sf->nroots * bytes)); 5025b0d146aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 5039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(rank, *win)); 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(0, *win)); 5055b0d146aSStefano Zampini } 5065b0d146aSStefano Zampini } 5075b0d146aSStefano Zampini link->inuse = PETSC_TRUE; 5085b0d146aSStefano Zampini link->epoch = epoch; 50995fce210SBarry Smith if (epoch) { 5105b0d146aSStefano Zampini switch (sync) { 511d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_SYNC_FENCE: 512d71ae5a4SJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(fenceassert, *win)); 513d71ae5a4SJacob Faibussowitsch break; 514d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ 515d71ae5a4SJacob Faibussowitsch break; 51695fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 51795fce210SBarry Smith MPI_Group ingroup, outgroup; 5185b0d146aSStefano Zampini PetscMPIInt isize, osize; 5195b0d146aSStefano Zampini 5205b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=vader does not like calling 5215b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 5225b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 5235b0d146aSStefano Zampini So, we do not even issue the corresponding start and post calls 5245b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 5255b0d146aSStefano Zampini start(outgroup) has a matching post(ingroup) 5265b0d146aSStefano Zampini and this is guaranteed by PetscSF 5275b0d146aSStefano Zampini */ 5289566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 5299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup, &isize)); 5309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup, &osize)); 5319566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_post(ingroup, postassert, *win)); 5329566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_start(outgroup, startassert, *win)); 53395fce210SBarry Smith } break; 534d71ae5a4SJacob Faibussowitsch default: 535d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type"); 53695fce210SBarry Smith } 53795fce210SBarry Smith } 53895fce210SBarry Smith PetscFunctionReturn(0); 53995fce210SBarry Smith } 54095fce210SBarry Smith 5415b0d146aSStefano Zampini /* 54295fce210SBarry Smith PetscSFFindWindow - Finds a window that is already in use 54395fce210SBarry Smith 54495fce210SBarry Smith Not Collective 54595fce210SBarry Smith 5464165533cSJose E. Roman Input Parameters: 54795fce210SBarry Smith + sf - star forest 54895fce210SBarry Smith . unit - data type 54995fce210SBarry Smith - array - array with which the window is associated 55095fce210SBarry Smith 5514165533cSJose E. Roman Output Parameters: 552684a874aSStefano Zampini + win - window 553684a874aSStefano Zampini - reqs - outstanding requests associated to the window 55495fce210SBarry Smith 55595fce210SBarry Smith Level: developer 55695fce210SBarry Smith 557cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFGetWindow()`, `PetscSFRestoreWindow()` 5585b0d146aSStefano Zampini */ 559d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFFindWindow(PetscSF sf, MPI_Datatype unit, const void *array, MPI_Win *win, MPI_Request **reqs) 560d71ae5a4SJacob Faibussowitsch { 56195fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 56295fce210SBarry Smith PetscSFWinLink link; 56395fce210SBarry Smith 56495fce210SBarry Smith PetscFunctionBegin; 565c0cd0301SJed Brown *win = MPI_WIN_NULL; 56695fce210SBarry Smith for (link = w->wins; link; link = link->next) { 5675b0d146aSStefano Zampini if (array == link->paddr) { 568*fef353a4SJacob Faibussowitsch PetscCall(PetscInfo(sf, "Window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)PetscObjectComm((PetscObject)sf))); 56995fce210SBarry Smith *win = link->win; 570684a874aSStefano Zampini *reqs = link->reqs; 57195fce210SBarry Smith PetscFunctionReturn(0); 57295fce210SBarry Smith } 57395fce210SBarry Smith } 57495fce210SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use"); 57595fce210SBarry Smith } 57695fce210SBarry Smith 5775b0d146aSStefano Zampini /* 578cab54364SBarry Smith PetscSFRestoreWindow - Restores a window obtained with `PetscSFGetWindow()` 57995fce210SBarry Smith 58095fce210SBarry Smith Collective 58195fce210SBarry Smith 5824165533cSJose E. Roman Input Parameters: 58395fce210SBarry Smith + sf - star forest 58495fce210SBarry Smith . unit - data type 58595fce210SBarry Smith . array - array associated with window 586cab54364SBarry Smith . sync - type of synchronization `PetscSFWindowSyncType` 587cab54364SBarry Smith . epoch - close an epoch, must match argument to `PetscSFGetWindow()` 5885b0d146aSStefano Zampini . update - if we have to update the local window array 58995fce210SBarry Smith - win - window 59095fce210SBarry Smith 59195fce210SBarry Smith Level: developer 59295fce210SBarry Smith 593cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFFindWindow()` 5945b0d146aSStefano Zampini */ 595d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFRestoreWindow(PetscSF sf, MPI_Datatype unit, void *array, PetscSFWindowSyncType sync, PetscBool epoch, PetscMPIInt fenceassert, PetscBool update, MPI_Win *win) 596d71ae5a4SJacob Faibussowitsch { 59795fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 59895fce210SBarry Smith PetscSFWinLink *p, link; 5995b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE; 6005b0d146aSStefano Zampini PetscSFWindowFlavorType flavor; 6015b0d146aSStefano Zampini void *laddr; 6025b0d146aSStefano Zampini size_t bytes; 60395fce210SBarry Smith 60495fce210SBarry Smith PetscFunctionBegin; 60595fce210SBarry Smith for (p = &w->wins; *p; p = &(*p)->next) { 60695fce210SBarry Smith link = *p; 60795fce210SBarry Smith if (*win == link->win) { 60808401ef6SPierre Jolivet PetscCheck(array == link->paddr, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Matched window, but not array"); 60995fce210SBarry Smith if (epoch != link->epoch) { 61028b400f6SJacob Faibussowitsch PetscCheck(!epoch, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "No epoch to end"); 611f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Restoring window without ending epoch"); 61295fce210SBarry Smith } 6135b0d146aSStefano Zampini laddr = link->addr; 6145b0d146aSStefano Zampini flavor = link->flavor; 6155b0d146aSStefano Zampini bytes = link->bytes; 6165b0d146aSStefano Zampini if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 6179371c9d4SSatish Balay else { 6189371c9d4SSatish Balay *p = link->next; 6199371c9d4SSatish Balay update = PETSC_FALSE; 6209371c9d4SSatish Balay } /* remove from list */ 62195fce210SBarry Smith goto found; 62295fce210SBarry Smith } 62395fce210SBarry Smith } 62495fce210SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use"); 62595fce210SBarry Smith 62695fce210SBarry Smith found: 627*fef353a4SJacob Faibussowitsch PetscCall(PetscInfo(sf, "Window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)PetscObjectComm((PetscObject)sf))); 62895fce210SBarry Smith if (epoch) { 6295b0d146aSStefano Zampini switch (sync) { 630d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_SYNC_FENCE: 631d71ae5a4SJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(fenceassert, *win)); 632d71ae5a4SJacob Faibussowitsch break; 633d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ 634d71ae5a4SJacob Faibussowitsch break; 63595fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 6365b0d146aSStefano Zampini MPI_Group ingroup, outgroup; 6375b0d146aSStefano Zampini PetscMPIInt isize, osize; 6385b0d146aSStefano Zampini 6395b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=wader does not like calling 6405b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 6415b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 6425b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 6435b0d146aSStefano Zampini - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete 6445b0d146aSStefano Zampini - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait 6455b0d146aSStefano Zampini */ 6469566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 6479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup, &isize)); 6489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup, &osize)); 6499566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_complete(*win)); 6509566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_wait(*win)); 65195fce210SBarry Smith } break; 652d71ae5a4SJacob Faibussowitsch default: 653d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type"); 65495fce210SBarry Smith } 65595fce210SBarry Smith } 6565b0d146aSStefano Zampini if (update) { 65748a46eb9SPierre Jolivet if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_fence(MPI_MODE_NOPUT | MPI_MODE_NOSUCCEED, *win)); 6589566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(array, laddr, sf->nroots * bytes)); 6595b0d146aSStefano Zampini } 6605b0d146aSStefano Zampini link->epoch = PETSC_FALSE; 6615b0d146aSStefano Zampini link->inuse = PETSC_FALSE; 6625b0d146aSStefano Zampini link->paddr = NULL; 6635b0d146aSStefano Zampini if (!reuse) { 6649566063dSJacob Faibussowitsch PetscCall(PetscFree(link->dyn_target_addr)); 6659566063dSJacob Faibussowitsch PetscCall(PetscFree(link->reqs)); 6669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&link->win)); 6679566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 66895fce210SBarry Smith *win = MPI_WIN_NULL; 6695b0d146aSStefano Zampini } 67095fce210SBarry Smith PetscFunctionReturn(0); 67195fce210SBarry Smith } 67295fce210SBarry Smith 673d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFSetUp_Window(PetscSF sf) 674d71ae5a4SJacob Faibussowitsch { 67595fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 67695fce210SBarry Smith MPI_Group ingroup, outgroup; 67795fce210SBarry Smith 67895fce210SBarry Smith PetscFunctionBegin; 6799566063dSJacob Faibussowitsch PetscCall(PetscSFSetUpRanks(sf, MPI_GROUP_EMPTY)); 6805b0d146aSStefano Zampini if (!w->dynsf) { 6815b0d146aSStefano Zampini PetscInt i; 6825b0d146aSStefano Zampini PetscSFNode *remotes; 6835b0d146aSStefano Zampini 6849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks, &remotes)); 6855b0d146aSStefano Zampini for (i = 0; i < sf->nranks; i++) { 6865b0d146aSStefano Zampini remotes[i].rank = sf->ranks[i]; 6875b0d146aSStefano Zampini remotes[i].index = 0; 6885b0d146aSStefano Zampini } 6899566063dSJacob Faibussowitsch PetscCall(PetscSFDuplicate(sf, PETSCSF_DUPLICATE_RANKS, &w->dynsf)); 6909566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(w->dynsf, PETSCSF_WINDOW_FLAVOR_CREATE)); /* break recursion */ 6919566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(w->dynsf, 1, sf->nranks, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 6925b0d146aSStefano Zampini } 69395fce210SBarry Smith switch (w->sync) { 694d71ae5a4SJacob Faibussowitsch case PETSCSF_WINDOW_SYNC_ACTIVE: 695d71ae5a4SJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 696d71ae5a4SJacob Faibussowitsch default: 697d71ae5a4SJacob Faibussowitsch break; 69895fce210SBarry Smith } 69995fce210SBarry Smith PetscFunctionReturn(0); 70095fce210SBarry Smith } 70195fce210SBarry Smith 702d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFSetFromOptions_Window(PetscSF sf, PetscOptionItems *PetscOptionsObject) 703d71ae5a4SJacob Faibussowitsch { 70495fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 7055b0d146aSStefano Zampini PetscSFWindowFlavorType flavor = w->flavor; 70695fce210SBarry Smith 70795fce210SBarry Smith PetscFunctionBegin; 708d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PetscSF Window options"); 7099566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_sync", "synchronization type to use for PetscSF Window communication", "PetscSFWindowSetSyncType", PetscSFWindowSyncTypes, (PetscEnum)w->sync, (PetscEnum *)&w->sync, NULL)); 7109566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_flavor", "flavor to use for PetscSF Window creation", "PetscSFWindowSetFlavorType", PetscSFWindowFlavorTypes, (PetscEnum)flavor, (PetscEnum *)&flavor, NULL)); 7119566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(sf, flavor)); 712d0609cedSBarry Smith PetscOptionsHeadEnd(); 71395fce210SBarry Smith PetscFunctionReturn(0); 71495fce210SBarry Smith } 71595fce210SBarry Smith 716d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFReset_Window(PetscSF sf) 717d71ae5a4SJacob Faibussowitsch { 71895fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 71995fce210SBarry Smith PetscSFDataLink link, next; 72095fce210SBarry Smith PetscSFWinLink wlink, wnext; 72195fce210SBarry Smith PetscInt i; 72295fce210SBarry Smith 72395fce210SBarry Smith PetscFunctionBegin; 72495fce210SBarry Smith for (link = w->link; link; link = next) { 72595fce210SBarry Smith next = link->next; 7269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->unit)); 72795fce210SBarry Smith for (i = 0; i < sf->nranks; i++) { 7289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->mine[i])); 7299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->remote[i])); 73095fce210SBarry Smith } 7319566063dSJacob Faibussowitsch PetscCall(PetscFree2(link->mine, link->remote)); 7329566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 73395fce210SBarry Smith } 73495fce210SBarry Smith w->link = NULL; 73595fce210SBarry Smith for (wlink = w->wins; wlink; wlink = wnext) { 73695fce210SBarry Smith wnext = wlink->next; 73728b400f6SJacob Faibussowitsch PetscCheck(!wlink->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_ARG_WRONGSTATE, "Window still in use with address %p", (void *)wlink->addr); 7389566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->dyn_target_addr)); 7399566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->reqs)); 7409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&wlink->win)); 7419566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink)); 74295fce210SBarry Smith } 74395fce210SBarry Smith w->wins = NULL; 7449566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&w->dynsf)); 74548a46eb9SPierre Jolivet if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info)); 74695fce210SBarry Smith PetscFunctionReturn(0); 74795fce210SBarry Smith } 74895fce210SBarry Smith 749d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFDestroy_Window(PetscSF sf) 750d71ae5a4SJacob Faibussowitsch { 75195fce210SBarry Smith PetscFunctionBegin; 7529566063dSJacob Faibussowitsch PetscCall(PetscSFReset_Window(sf)); 7539566063dSJacob Faibussowitsch PetscCall(PetscFree(sf->data)); 7549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", NULL)); 7559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", NULL)); 7569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", NULL)); 7579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", NULL)); 7589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", NULL)); 7599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", NULL)); 76095fce210SBarry Smith PetscFunctionReturn(0); 76195fce210SBarry Smith } 76295fce210SBarry Smith 763d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFView_Window(PetscSF sf, PetscViewer viewer) 764d71ae5a4SJacob Faibussowitsch { 76595fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 76695fce210SBarry Smith PetscBool iascii; 7675b0d146aSStefano Zampini PetscViewerFormat format; 76895fce210SBarry Smith 76995fce210SBarry Smith PetscFunctionBegin; 7709566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 77295fce210SBarry Smith if (iascii) { 7739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current flavor=%s synchronization=%s MultiSF sort=%s\n", PetscSFWindowFlavorTypes[w->flavor], PetscSFWindowSyncTypes[w->sync], sf->rankorder ? "rank-order" : "unordered")); 7745b0d146aSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 7755b0d146aSStefano Zampini if (w->info != MPI_INFO_NULL) { 7765b0d146aSStefano Zampini PetscMPIInt k, nkeys; 7775b0d146aSStefano Zampini char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL]; 7785b0d146aSStefano Zampini 7799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nkeys(w->info, &nkeys)); 7809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current info with %d keys. Ordered key-value pairs follow:\n", nkeys)); 7815b0d146aSStefano Zampini for (k = 0; k < nkeys; k++) { 7825b0d146aSStefano Zampini PetscMPIInt flag; 7835b0d146aSStefano Zampini 7849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nthkey(w->info, k, key)); 7859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get(w->info, key, MPI_MAX_INFO_VAL, value, &flag)); 78628b400f6SJacob Faibussowitsch PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing key %s", key); 7879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s = %s\n", key, value)); 7885b0d146aSStefano Zampini } 7895b0d146aSStefano Zampini } else { 7909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current info=MPI_INFO_NULL\n")); 7915b0d146aSStefano Zampini } 7925b0d146aSStefano Zampini } 79395fce210SBarry Smith } 79495fce210SBarry Smith PetscFunctionReturn(0); 79595fce210SBarry Smith } 79695fce210SBarry Smith 797d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf, PetscSFDuplicateOption opt, PetscSF newsf) 798d71ae5a4SJacob Faibussowitsch { 79995fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 80095fce210SBarry Smith PetscSFWindowSyncType synctype; 80195fce210SBarry Smith 80295fce210SBarry Smith PetscFunctionBegin; 80395fce210SBarry Smith synctype = w->sync; 80495fce210SBarry Smith /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */ 8055b0d146aSStefano Zampini if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK; 8069566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetSyncType(newsf, synctype)); 8079566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(newsf, w->flavor)); 8089566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetInfo(newsf, w->info)); 80995fce210SBarry Smith PetscFunctionReturn(0); 81095fce210SBarry Smith } 81195fce210SBarry Smith 812d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, const void *rootdata, PetscMemType leafmtype, void *leafdata, MPI_Op op) 813d71ae5a4SJacob Faibussowitsch { 81495fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 81595fce210SBarry Smith PetscInt i, nranks; 81695fce210SBarry Smith const PetscMPIInt *ranks; 8175b0d146aSStefano Zampini const MPI_Aint *target_disp; 81895fce210SBarry Smith const MPI_Datatype *mine, *remote; 819684a874aSStefano Zampini MPI_Request *reqs; 82095fce210SBarry Smith MPI_Win win; 82195fce210SBarry Smith 82295fce210SBarry Smith PetscFunctionBegin; 82308401ef6SPierre Jolivet PetscCheck(op == MPI_REPLACE, PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented"); 8249566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 8259566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote)); 8269566063dSJacob 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)); 82795fce210SBarry Smith for (i = 0; i < nranks; i++) { 8285b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 8295b0d146aSStefano Zampini 830684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 8319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win)); 832684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET) 8339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Rget(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win, &reqs[i])); 834684a874aSStefano Zampini #else 8359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win)); 836684a874aSStefano Zampini #endif 837684a874aSStefano Zampini } else { 8389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win)); 839684a874aSStefano Zampini } 84095fce210SBarry Smith } 84195fce210SBarry Smith PetscFunctionReturn(0); 84295fce210SBarry Smith } 84395fce210SBarry Smith 844d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, void *leafdata, MPI_Op op) 845d71ae5a4SJacob Faibussowitsch { 8465b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 84795fce210SBarry Smith MPI_Win win; 8484b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 84995fce210SBarry Smith 85095fce210SBarry Smith PetscFunctionBegin; 8519566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs)); 8529566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE)); 853684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 854684a874aSStefano Zampini PetscInt i, nranks; 855684a874aSStefano Zampini const PetscMPIInt *ranks; 856684a874aSStefano Zampini 8579566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 85848a46eb9SPierre Jolivet for (i = 0; i < nranks; i++) PetscCallMPI(MPI_Win_unlock(ranks[i], win)); 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 864d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType leafmtype, const void *leafdata, PetscMemType rootmtype, void *rootdata, MPI_Op op) 865d71ae5a4SJacob Faibussowitsch { 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 888d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf, MPI_Datatype unit, const void *leafdata, void *rootdata, MPI_Op op) 889d71ae5a4SJacob Faibussowitsch { 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 901d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, void *rootdata, PetscMemType leafmtype, const void *leafdata, void *leafupdate, MPI_Op op) 902d71ae5a4SJacob Faibussowitsch { 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 946d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf, MPI_Datatype unit, void *rootdata, const void *leafdata, void *leafupdate, MPI_Op op) 947d71ae5a4SJacob Faibussowitsch { 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 965d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf) 966d71ae5a4SJacob Faibussowitsch { 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 9834dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&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