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) */ 399371c9d4SSatish Balay static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op) { 4095fce210SBarry Smith PetscFunctionBegin; 4195fce210SBarry Smith if (*op == MPIU_SUM) *op = MPI_SUM; 4295fce210SBarry Smith else if (*op == MPIU_MAX) *op = MPI_MAX; 4395fce210SBarry Smith else if (*op == MPIU_MIN) *op = MPI_MIN; 4495fce210SBarry Smith PetscFunctionReturn(0); 4595fce210SBarry Smith } 4695fce210SBarry Smith 4795fce210SBarry Smith /*@C 4895fce210SBarry Smith PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank 4995fce210SBarry Smith 5095fce210SBarry Smith Not Collective 5195fce210SBarry Smith 524165533cSJose E. Roman Input Parameters: 5395fce210SBarry Smith + sf - star forest 5495fce210SBarry Smith - unit - data type for each node 5595fce210SBarry Smith 564165533cSJose E. Roman Output Parameters: 5795fce210SBarry Smith + localtypes - types describing part of local leaf buffer referencing each remote rank 5895fce210SBarry Smith - remotetypes - types describing part of remote root buffer referenced for each remote rank 5995fce210SBarry Smith 6095fce210SBarry Smith Level: developer 6195fce210SBarry Smith 62db781477SPatrick Sanan .seealso: `PetscSFSetGraph()`, `PetscSFView()` 6395fce210SBarry Smith @*/ 649371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf, MPI_Datatype unit, const MPI_Datatype **localtypes, const MPI_Datatype **remotetypes) { 6595fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 6695fce210SBarry Smith PetscSFDataLink link; 6795fce210SBarry Smith PetscInt i, nranks; 6895fce210SBarry Smith const PetscInt *roffset, *rmine, *rremote; 6995fce210SBarry Smith const PetscMPIInt *ranks; 7095fce210SBarry Smith 7195fce210SBarry Smith PetscFunctionBegin; 7295fce210SBarry Smith /* Look for types in cache */ 7395fce210SBarry Smith for (link = w->link; link; link = link->next) { 7495fce210SBarry Smith PetscBool match; 759566063dSJacob Faibussowitsch PetscCall(MPIPetsc_Type_compare(unit, link->unit, &match)); 7695fce210SBarry Smith if (match) { 7795fce210SBarry Smith *localtypes = link->mine; 7895fce210SBarry Smith *remotetypes = link->remote; 7995fce210SBarry Smith PetscFunctionReturn(0); 8095fce210SBarry Smith } 8195fce210SBarry Smith } 8295fce210SBarry Smith 8395fce210SBarry Smith /* Create new composite types for each send rank */ 849566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote)); 859566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_dup(unit, &link->unit)); 879566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nranks, &link->mine, nranks, &link->remote)); 8895fce210SBarry Smith for (i = 0; i < nranks; i++) { 895b0d146aSStefano Zampini PetscInt rcount = roffset[i + 1] - roffset[i]; 9095fce210SBarry Smith PetscMPIInt *rmine, *rremote; 9195fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES) 9295fce210SBarry Smith rmine = sf->rmine + sf->roffset[i]; 9395fce210SBarry Smith rremote = sf->rremote + sf->roffset[i]; 9495fce210SBarry Smith #else 9595fce210SBarry Smith PetscInt j; 969566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(rcount, &rmine, rcount, &rremote)); 9795fce210SBarry Smith for (j = 0; j < rcount; j++) { 989566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(sf->rmine[sf->roffset[i] + j], rmine + j)); 999566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(sf->rremote[sf->roffset[i] + j], rremote + j)); 10095fce210SBarry Smith } 10195fce210SBarry Smith #endif 1025b0d146aSStefano Zampini 1039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rmine, link->unit, &link->mine[i])); 1049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rremote, link->unit, &link->remote[i])); 10595fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES) 1069566063dSJacob Faibussowitsch PetscCall(PetscFree2(rmine, rremote)); 10795fce210SBarry Smith #endif 1089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&link->mine[i])); 1099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&link->remote[i])); 11095fce210SBarry Smith } 11195fce210SBarry Smith link->next = w->link; 11295fce210SBarry Smith w->link = link; 11395fce210SBarry Smith 11495fce210SBarry Smith *localtypes = link->mine; 11595fce210SBarry Smith *remotetypes = link->remote; 11695fce210SBarry Smith PetscFunctionReturn(0); 11795fce210SBarry Smith } 11895fce210SBarry Smith 11995fce210SBarry Smith /*@C 1205b0d146aSStefano Zampini PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation 1215b0d146aSStefano Zampini 1225b0d146aSStefano Zampini Logically Collective 1235b0d146aSStefano Zampini 1244165533cSJose E. Roman Input Parameters: 1255b0d146aSStefano Zampini + sf - star forest for communication 1265b0d146aSStefano Zampini - flavor - flavor type 1275b0d146aSStefano Zampini 1285b0d146aSStefano Zampini Options Database Key: 1295b0d146aSStefano Zampini . -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType) 1305b0d146aSStefano Zampini 1315b0d146aSStefano Zampini Level: advanced 1325b0d146aSStefano Zampini 1335b0d146aSStefano Zampini Notes: Windows reusage follow this rules: 1345b0d146aSStefano Zampini 1355b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create 1365b0d146aSStefano Zampini 1375b0d146aSStefano 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. 1385b0d146aSStefano Zampini for i=1 to K 1395b0d146aSStefano Zampini PetscSFOperationBegin(rootdata1,leafdata_whatever); 1405b0d146aSStefano Zampini PetscSFOperationEnd(rootdata1,leafdata_whatever); 1415b0d146aSStefano Zampini ... 1425b0d146aSStefano Zampini PetscSFOperationBegin(rootdataN,leafdata_whatever); 1435b0d146aSStefano Zampini PetscSFOperationEnd(rootdataN,leafdata_whatever); 1445b0d146aSStefano Zampini endfor 1455b0d146aSStefano Zampini The following pattern will instead raise an error 1465b0d146aSStefano Zampini PetscSFOperationBegin(rootdata1,leafdata_whatever); 1475b0d146aSStefano Zampini PetscSFOperationEnd(rootdata1,leafdata_whatever); 1485b0d146aSStefano Zampini PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever); 1495b0d146aSStefano Zampini PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever); 1505b0d146aSStefano Zampini 1515b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use 1525b0d146aSStefano Zampini 1535b0d146aSStefano Zampini PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE 1545b0d146aSStefano Zampini 155db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetFlavorType()` 1565b0d146aSStefano Zampini @*/ 1579371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf, PetscSFWindowFlavorType flavor) { 1585b0d146aSStefano Zampini PetscFunctionBegin; 1595b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 1605b0d146aSStefano Zampini PetscValidLogicalCollectiveEnum(sf, flavor, 2); 161cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetFlavorType_C", (PetscSF, PetscSFWindowFlavorType), (sf, flavor)); 1625b0d146aSStefano Zampini PetscFunctionReturn(0); 1635b0d146aSStefano Zampini } 1645b0d146aSStefano Zampini 1659371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType flavor) { 1665b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 1675b0d146aSStefano Zampini 1685b0d146aSStefano Zampini PetscFunctionBegin; 1695b0d146aSStefano Zampini w->flavor = flavor; 1705b0d146aSStefano Zampini PetscFunctionReturn(0); 1715b0d146aSStefano Zampini } 1725b0d146aSStefano Zampini 1735b0d146aSStefano Zampini /*@C 1745b0d146aSStefano Zampini PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication 1755b0d146aSStefano Zampini 1765b0d146aSStefano Zampini Logically Collective 1775b0d146aSStefano Zampini 1784165533cSJose E. Roman Input Parameter: 1795b0d146aSStefano Zampini . sf - star forest for communication 1805b0d146aSStefano Zampini 1814165533cSJose E. Roman Output Parameter: 1825b0d146aSStefano Zampini . flavor - flavor type 1835b0d146aSStefano Zampini 1845b0d146aSStefano Zampini Level: advanced 1855b0d146aSStefano Zampini 186db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetFlavorType()` 1875b0d146aSStefano Zampini @*/ 1889371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf, PetscSFWindowFlavorType *flavor) { 1895b0d146aSStefano Zampini PetscFunctionBegin; 1905b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 1915b0d146aSStefano Zampini PetscValidPointer(flavor, 2); 192cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetFlavorType_C", (PetscSF, PetscSFWindowFlavorType *), (sf, flavor)); 1935b0d146aSStefano Zampini PetscFunctionReturn(0); 1945b0d146aSStefano Zampini } 1955b0d146aSStefano Zampini 1969371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType *flavor) { 1975b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 1985b0d146aSStefano Zampini 1995b0d146aSStefano Zampini PetscFunctionBegin; 2005b0d146aSStefano Zampini *flavor = w->flavor; 2015b0d146aSStefano Zampini PetscFunctionReturn(0); 2025b0d146aSStefano Zampini } 2035b0d146aSStefano Zampini 2045b0d146aSStefano Zampini /*@C 2055b0d146aSStefano Zampini PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication 20695fce210SBarry Smith 20795fce210SBarry Smith Logically Collective 20895fce210SBarry Smith 2094165533cSJose E. Roman Input Parameters: 21095fce210SBarry Smith + sf - star forest for communication 21195fce210SBarry Smith - sync - synchronization type 21295fce210SBarry Smith 21395fce210SBarry Smith Options Database Key: 21460263706SJed Brown . -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType) 21595fce210SBarry Smith 21695fce210SBarry Smith Level: advanced 21795fce210SBarry Smith 218db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetSyncType()` 21995fce210SBarry Smith @*/ 2209371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf, PetscSFWindowSyncType sync) { 22195fce210SBarry Smith PetscFunctionBegin; 22295fce210SBarry Smith PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 22395fce210SBarry Smith PetscValidLogicalCollectiveEnum(sf, sync, 2); 224cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetSyncType_C", (PetscSF, PetscSFWindowSyncType), (sf, sync)); 22595fce210SBarry Smith PetscFunctionReturn(0); 22695fce210SBarry Smith } 22795fce210SBarry Smith 2289371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf, PetscSFWindowSyncType sync) { 22995fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 23095fce210SBarry Smith 23195fce210SBarry Smith PetscFunctionBegin; 23295fce210SBarry Smith w->sync = sync; 23395fce210SBarry Smith PetscFunctionReturn(0); 23495fce210SBarry Smith } 23595fce210SBarry Smith 23695fce210SBarry Smith /*@C 2375b0d146aSStefano Zampini PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication 23895fce210SBarry Smith 23995fce210SBarry Smith Logically Collective 24095fce210SBarry Smith 2414165533cSJose E. Roman Input Parameter: 24295fce210SBarry Smith . sf - star forest for communication 24395fce210SBarry Smith 2444165533cSJose E. Roman Output Parameter: 24595fce210SBarry Smith . sync - synchronization type 24695fce210SBarry Smith 24795fce210SBarry Smith Level: advanced 24895fce210SBarry Smith 249db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetSyncType()` 25095fce210SBarry Smith @*/ 2519371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf, PetscSFWindowSyncType *sync) { 25295fce210SBarry Smith PetscFunctionBegin; 25395fce210SBarry Smith PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 25495fce210SBarry Smith PetscValidPointer(sync, 2); 255cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetSyncType_C", (PetscSF, PetscSFWindowSyncType *), (sf, sync)); 25695fce210SBarry Smith PetscFunctionReturn(0); 25795fce210SBarry Smith } 25895fce210SBarry Smith 2599371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf, PetscSFWindowSyncType *sync) { 26095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 26195fce210SBarry Smith 26295fce210SBarry Smith PetscFunctionBegin; 26395fce210SBarry Smith *sync = w->sync; 26495fce210SBarry Smith PetscFunctionReturn(0); 26595fce210SBarry Smith } 26695fce210SBarry Smith 26795fce210SBarry Smith /*@C 2685b0d146aSStefano Zampini PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation 2695b0d146aSStefano Zampini 2705b0d146aSStefano Zampini Logically Collective 2715b0d146aSStefano Zampini 2724165533cSJose E. Roman Input Parameters: 2735b0d146aSStefano Zampini + sf - star forest for communication 2745b0d146aSStefano Zampini - info - MPI_Info handle 2755b0d146aSStefano Zampini 2765b0d146aSStefano Zampini Level: advanced 2775b0d146aSStefano Zampini 2785b0d146aSStefano Zampini Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL. 2795b0d146aSStefano Zampini 280db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetInfo()` 2815b0d146aSStefano Zampini @*/ 2829371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetInfo(PetscSF sf, MPI_Info info) { 2835b0d146aSStefano Zampini PetscFunctionBegin; 2845b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 285cac4c232SBarry Smith PetscTryMethod(sf, "PetscSFWindowSetInfo_C", (PetscSF, MPI_Info), (sf, info)); 2865b0d146aSStefano Zampini PetscFunctionReturn(0); 2875b0d146aSStefano Zampini } 2885b0d146aSStefano Zampini 2899371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf, MPI_Info info) { 2905b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 2915b0d146aSStefano Zampini 2925b0d146aSStefano Zampini PetscFunctionBegin; 293*48a46eb9SPierre Jolivet if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info)); 294*48a46eb9SPierre Jolivet if (info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_dup(info, &w->info)); 2955b0d146aSStefano Zampini PetscFunctionReturn(0); 2965b0d146aSStefano Zampini } 2975b0d146aSStefano Zampini 2985b0d146aSStefano Zampini /*@C 2995b0d146aSStefano Zampini PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation 3005b0d146aSStefano Zampini 3015b0d146aSStefano Zampini Logically Collective 3025b0d146aSStefano Zampini 3034165533cSJose E. Roman Input Parameter: 3045b0d146aSStefano Zampini . sf - star forest for communication 3055b0d146aSStefano Zampini 3064165533cSJose E. Roman Output Parameter: 3075b0d146aSStefano Zampini . info - MPI_Info handle 3085b0d146aSStefano Zampini 3095b0d146aSStefano Zampini Level: advanced 3105b0d146aSStefano Zampini 3115b0d146aSStefano Zampini Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL 3125b0d146aSStefano Zampini 313db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetInfo()` 3145b0d146aSStefano Zampini @*/ 3159371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetInfo(PetscSF sf, MPI_Info *info) { 3165b0d146aSStefano Zampini PetscFunctionBegin; 3175b0d146aSStefano Zampini PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3185b0d146aSStefano Zampini PetscValidPointer(info, 2); 319cac4c232SBarry Smith PetscUseMethod(sf, "PetscSFWindowGetInfo_C", (PetscSF, MPI_Info *), (sf, info)); 3205b0d146aSStefano Zampini PetscFunctionReturn(0); 3215b0d146aSStefano Zampini } 3225b0d146aSStefano Zampini 3239371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf, MPI_Info *info) { 3245b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 3255b0d146aSStefano Zampini 3265b0d146aSStefano Zampini PetscFunctionBegin; 3275b0d146aSStefano Zampini *info = w->info; 3285b0d146aSStefano Zampini PetscFunctionReturn(0); 3295b0d146aSStefano Zampini } 3305b0d146aSStefano Zampini 3315b0d146aSStefano Zampini /* 33295fce210SBarry Smith PetscSFGetWindow - Get a window for use with a given data type 33395fce210SBarry Smith 33495fce210SBarry Smith Collective on PetscSF 33595fce210SBarry Smith 3364165533cSJose E. Roman Input Parameters: 33795fce210SBarry Smith + sf - star forest 33895fce210SBarry Smith . unit - data type 33995fce210SBarry Smith . array - array to be sent 3405b0d146aSStefano Zampini . sync - type of synchronization PetscSFWindowSyncType 34195fce210SBarry Smith . epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window 3425b0d146aSStefano Zampini . fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE 3435b0d146aSStefano Zampini . postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE 344684a874aSStefano Zampini - startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE 34595fce210SBarry Smith 3464165533cSJose E. Roman Output Parameters: 347684a874aSStefano Zampini + target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only) 348684a874aSStefano Zampini + reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only) 349684a874aSStefano Zampini - win - window 35095fce210SBarry Smith 35195fce210SBarry Smith Level: developer 352db781477SPatrick Sanan .seealso: `PetscSFGetRootRanks()`, `PetscSFWindowGetDataTypes()` 3535b0d146aSStefano Zampini */ 3549371c9d4SSatish Balay 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) { 35595fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 35695fce210SBarry Smith MPI_Aint lb, lb_true, bytes, bytes_true; 35795fce210SBarry Smith PetscSFWinLink link; 358d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 3595b0d146aSStefano Zampini MPI_Aint winaddr; 3605b0d146aSStefano Zampini PetscInt nranks; 361d547623eSJunchao Zhang #endif 3625b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE, update = PETSC_FALSE; 3635b0d146aSStefano Zampini PetscBool dummy[2]; 3645b0d146aSStefano Zampini MPI_Aint wsize; 36595fce210SBarry Smith 36695fce210SBarry Smith PetscFunctionBegin; 3679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_extent(unit, &lb, &bytes)); 3689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_get_true_extent(unit, &lb_true, &bytes_true)); 369c9cc58a2SBarry 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"); 37008401ef6SPierre 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"); 3715b0d146aSStefano Zampini if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 3725b0d146aSStefano Zampini for (link = w->wins; reuse && link; link = link->next) { 3735b0d146aSStefano Zampini PetscBool winok = PETSC_FALSE; 3745b0d146aSStefano Zampini if (w->flavor != link->flavor) continue; 3755b0d146aSStefano Zampini switch (w->flavor) { 3765b0d146aSStefano 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) */ 3775b0d146aSStefano Zampini if (array == link->addr) { 37876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3795b0d146aSStefano Zampini dummy[0] = PETSC_TRUE; 3805b0d146aSStefano Zampini dummy[1] = PETSC_TRUE; 3819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf))); 3829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf))); 38308401ef6SPierre 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"); 38476bd3646SJed Brown } 38528b400f6SJacob Faibussowitsch PetscCheck(!link->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window in use"); 38608401ef6SPierre Jolivet PetscCheck(!epoch || !link->epoch, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window epoch not finished"); 3875b0d146aSStefano Zampini winok = PETSC_TRUE; 3885b0d146aSStefano Zampini link->paddr = array; 38976bd3646SJed Brown } else if (PetscDefined(USE_DEBUG)) { 3905b0d146aSStefano Zampini dummy[0] = PETSC_FALSE; 3915b0d146aSStefano Zampini dummy[1] = PETSC_FALSE; 3929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf))); 3939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf))); 39408401ef6SPierre 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"); 3955b0d146aSStefano Zampini } 3965b0d146aSStefano Zampini break; 3975b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */ 3985b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 3995b0d146aSStefano Zampini if (!link->inuse && bytes == (MPI_Aint)link->bytes) { 4005b0d146aSStefano Zampini update = PETSC_TRUE; 4015b0d146aSStefano Zampini link->paddr = array; 4025b0d146aSStefano Zampini winok = PETSC_TRUE; 4035b0d146aSStefano Zampini } 4045b0d146aSStefano Zampini break; 40598921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]); 4065b0d146aSStefano Zampini } 4075b0d146aSStefano Zampini if (winok) { 4085b0d146aSStefano Zampini *win = link->win; 4099566063dSJacob 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))); 4105b0d146aSStefano Zampini goto found; 4115b0d146aSStefano Zampini } 4125b0d146aSStefano Zampini } 4135b0d146aSStefano Zampini 4145b0d146aSStefano Zampini wsize = (MPI_Aint)bytes * sf->nroots; 4159566063dSJacob Faibussowitsch PetscCall(PetscNew(&link)); 41695fce210SBarry Smith link->bytes = bytes; 41795fce210SBarry Smith link->next = w->wins; 4185b0d146aSStefano Zampini link->flavor = w->flavor; 4195b0d146aSStefano Zampini link->dyn_target_addr = NULL; 420684a874aSStefano Zampini link->reqs = NULL; 42195fce210SBarry Smith w->wins = link; 422684a874aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 423684a874aSStefano Zampini PetscInt i; 424684a874aSStefano Zampini 4259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks, &link->reqs)); 426684a874aSStefano Zampini for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL; 427684a874aSStefano Zampini } 4285b0d146aSStefano Zampini switch (w->flavor) { 4295b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_CREATE: 4309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_create(array, wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->win)); 4315b0d146aSStefano Zampini link->addr = array; 4325b0d146aSStefano Zampini link->paddr = array; 4335b0d146aSStefano Zampini break; 434d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW) 4359371c9d4SSatish Balay case PETSCSF_WINDOW_FLAVOR_DYNAMIC: PetscCallMPI(MPI_Win_create_dynamic(w->info, PetscObjectComm((PetscObject)sf), &link->win)); 4365b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */ 437244dd087SJunchao Zhang PetscCallMPI(MPI_Win_attach(link->win, wsize ? array : (void *)dummy, wsize)); 4385b0d146aSStefano Zampini #else 4399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_attach(link->win, array, wsize)); 4405b0d146aSStefano Zampini #endif 4415b0d146aSStefano Zampini link->addr = array; 4425b0d146aSStefano Zampini link->paddr = array; 44328b400f6SJacob Faibussowitsch PetscCheck(w->dynsf, PetscObjectComm((PetscObject)sf), PETSC_ERR_ORDER, "Must call PetscSFSetUp()"); 4449566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(w->dynsf)); 4459566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(w->dynsf, &nranks, NULL, NULL, NULL, NULL)); 4469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nranks, &link->dyn_target_addr)); 4479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get_address(array, &winaddr)); 4489566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE)); 4499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE)); 4505b0d146aSStefano Zampini break; 4515b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_ALLOCATE: 4529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win)); 4535b0d146aSStefano Zampini update = PETSC_TRUE; 4545b0d146aSStefano Zampini link->paddr = array; 4555b0d146aSStefano Zampini break; 456d547623eSJunchao Zhang #endif 4575b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 4585b0d146aSStefano Zampini case PETSCSF_WINDOW_FLAVOR_SHARED: 4599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_allocate_shared(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win)); 4605b0d146aSStefano Zampini update = PETSC_TRUE; 4615b0d146aSStefano Zampini link->paddr = array; 4625b0d146aSStefano Zampini break; 4635b0d146aSStefano Zampini #endif 46498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]); 4655b0d146aSStefano Zampini } 4669566063dSJacob 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))); 46795fce210SBarry Smith *win = link->win; 46895fce210SBarry Smith 4695b0d146aSStefano Zampini found: 4705b0d146aSStefano Zampini 471684a874aSStefano Zampini if (target_disp) *target_disp = link->dyn_target_addr; 472684a874aSStefano Zampini if (reqs) *reqs = link->reqs; 473684a874aSStefano Zampini if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */ 474684a874aSStefano Zampini PetscMPIInt rank; 475684a874aSStefano Zampini 4769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sf), &rank)); 4779566063dSJacob Faibussowitsch if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, MPI_MODE_NOCHECK, *win)); 4789566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(link->addr, array, sf->nroots * bytes)); 4795b0d146aSStefano Zampini if (sync == PETSCSF_WINDOW_SYNC_LOCK) { 4809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(rank, *win)); 4819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_fence(0, *win)); 4825b0d146aSStefano Zampini } 4835b0d146aSStefano Zampini } 4845b0d146aSStefano Zampini link->inuse = PETSC_TRUE; 4855b0d146aSStefano Zampini link->epoch = epoch; 48695fce210SBarry Smith if (epoch) { 4875b0d146aSStefano Zampini switch (sync) { 4889371c9d4SSatish Balay case PETSCSF_WINDOW_SYNC_FENCE: PetscCallMPI(MPI_Win_fence(fenceassert, *win)); break; 4899371c9d4SSatish Balay case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ break; 49095fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 49195fce210SBarry Smith MPI_Group ingroup, outgroup; 4925b0d146aSStefano Zampini PetscMPIInt isize, osize; 4935b0d146aSStefano Zampini 4945b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=vader does not like calling 4955b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 4965b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 4975b0d146aSStefano Zampini So, we do not even issue the corresponding start and post calls 4985b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 4995b0d146aSStefano Zampini start(outgroup) has a matching post(ingroup) 5005b0d146aSStefano Zampini and this is guaranteed by PetscSF 5015b0d146aSStefano Zampini */ 5029566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 5039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup, &isize)); 5049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup, &osize)); 5059566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_post(ingroup, postassert, *win)); 5069566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_start(outgroup, startassert, *win)); 50795fce210SBarry Smith } break; 50895fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type"); 50995fce210SBarry Smith } 51095fce210SBarry Smith } 51195fce210SBarry Smith PetscFunctionReturn(0); 51295fce210SBarry Smith } 51395fce210SBarry Smith 5145b0d146aSStefano Zampini /* 51595fce210SBarry Smith PetscSFFindWindow - Finds a window that is already in use 51695fce210SBarry Smith 51795fce210SBarry Smith Not Collective 51895fce210SBarry Smith 5194165533cSJose E. Roman Input Parameters: 52095fce210SBarry Smith + sf - star forest 52195fce210SBarry Smith . unit - data type 52295fce210SBarry Smith - array - array with which the window is associated 52395fce210SBarry Smith 5244165533cSJose E. Roman Output Parameters: 525684a874aSStefano Zampini + win - window 526684a874aSStefano Zampini - reqs - outstanding requests associated to the window 52795fce210SBarry Smith 52895fce210SBarry Smith Level: developer 52995fce210SBarry Smith 530db781477SPatrick Sanan .seealso: `PetscSFGetWindow()`, `PetscSFRestoreWindow()` 5315b0d146aSStefano Zampini */ 5329371c9d4SSatish Balay static PetscErrorCode PetscSFFindWindow(PetscSF sf, MPI_Datatype unit, const void *array, MPI_Win *win, MPI_Request **reqs) { 53395fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 53495fce210SBarry Smith PetscSFWinLink link; 53595fce210SBarry Smith 53695fce210SBarry Smith PetscFunctionBegin; 537c0cd0301SJed Brown *win = MPI_WIN_NULL; 53895fce210SBarry Smith for (link = w->wins; link; link = link->next) { 5395b0d146aSStefano Zampini if (array == link->paddr) { 5409566063dSJacob 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))); 54195fce210SBarry Smith *win = link->win; 542684a874aSStefano Zampini *reqs = link->reqs; 54395fce210SBarry Smith PetscFunctionReturn(0); 54495fce210SBarry Smith } 54595fce210SBarry Smith } 54695fce210SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use"); 54795fce210SBarry Smith } 54895fce210SBarry Smith 5495b0d146aSStefano Zampini /* 55095fce210SBarry Smith PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow() 55195fce210SBarry Smith 55295fce210SBarry Smith Collective 55395fce210SBarry Smith 5544165533cSJose E. Roman Input Parameters: 55595fce210SBarry Smith + sf - star forest 55695fce210SBarry Smith . unit - data type 55795fce210SBarry Smith . array - array associated with window 5585b0d146aSStefano Zampini . sync - type of synchronization PetscSFWindowSyncType 55995fce210SBarry Smith . epoch - close an epoch, must match argument to PetscSFGetWindow() 5605b0d146aSStefano Zampini . update - if we have to update the local window array 56195fce210SBarry Smith - win - window 56295fce210SBarry Smith 56395fce210SBarry Smith Level: developer 56495fce210SBarry Smith 565db781477SPatrick Sanan .seealso: `PetscSFFindWindow()` 5665b0d146aSStefano Zampini */ 5679371c9d4SSatish Balay static PetscErrorCode PetscSFRestoreWindow(PetscSF sf, MPI_Datatype unit, void *array, PetscSFWindowSyncType sync, PetscBool epoch, PetscMPIInt fenceassert, PetscBool update, MPI_Win *win) { 56895fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 56995fce210SBarry Smith PetscSFWinLink *p, link; 5705b0d146aSStefano Zampini PetscBool reuse = PETSC_FALSE; 5715b0d146aSStefano Zampini PetscSFWindowFlavorType flavor; 5725b0d146aSStefano Zampini void *laddr; 5735b0d146aSStefano Zampini size_t bytes; 57495fce210SBarry Smith 57595fce210SBarry Smith PetscFunctionBegin; 57695fce210SBarry Smith for (p = &w->wins; *p; p = &(*p)->next) { 57795fce210SBarry Smith link = *p; 57895fce210SBarry Smith if (*win == link->win) { 57908401ef6SPierre Jolivet PetscCheck(array == link->paddr, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Matched window, but not array"); 58095fce210SBarry Smith if (epoch != link->epoch) { 58128b400f6SJacob Faibussowitsch PetscCheck(!epoch, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "No epoch to end"); 582f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Restoring window without ending epoch"); 58395fce210SBarry Smith } 5845b0d146aSStefano Zampini laddr = link->addr; 5855b0d146aSStefano Zampini flavor = link->flavor; 5865b0d146aSStefano Zampini bytes = link->bytes; 5875b0d146aSStefano Zampini if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE; 5889371c9d4SSatish Balay else { 5899371c9d4SSatish Balay *p = link->next; 5909371c9d4SSatish Balay update = PETSC_FALSE; 5919371c9d4SSatish Balay } /* remove from list */ 59295fce210SBarry Smith goto found; 59395fce210SBarry Smith } 59495fce210SBarry Smith } 59595fce210SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use"); 59695fce210SBarry Smith 59795fce210SBarry Smith found: 5989566063dSJacob 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))); 59995fce210SBarry Smith if (epoch) { 6005b0d146aSStefano Zampini switch (sync) { 6019371c9d4SSatish Balay case PETSCSF_WINDOW_SYNC_FENCE: PetscCallMPI(MPI_Win_fence(fenceassert, *win)); break; 6029371c9d4SSatish Balay case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ break; 60395fce210SBarry Smith case PETSCSF_WINDOW_SYNC_ACTIVE: { 6045b0d146aSStefano Zampini MPI_Group ingroup, outgroup; 6055b0d146aSStefano Zampini PetscMPIInt isize, osize; 6065b0d146aSStefano Zampini 6075b0d146aSStefano Zampini /* OpenMPI 4.0.2 with btl=wader does not like calling 6085b0d146aSStefano Zampini - MPI_Win_complete when ogroup is empty 6095b0d146aSStefano Zampini - MPI_Win_wait when igroup is empty 6105b0d146aSStefano Zampini The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that 6115b0d146aSStefano Zampini - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete 6125b0d146aSStefano Zampini - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait 6135b0d146aSStefano Zampini */ 6149566063dSJacob Faibussowitsch PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 6159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(ingroup, &isize)); 6169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_size(outgroup, &osize)); 6179566063dSJacob Faibussowitsch if (osize) PetscCallMPI(MPI_Win_complete(*win)); 6189566063dSJacob Faibussowitsch if (isize) PetscCallMPI(MPI_Win_wait(*win)); 61995fce210SBarry Smith } break; 62095fce210SBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type"); 62195fce210SBarry Smith } 62295fce210SBarry Smith } 6235b0d146aSStefano Zampini if (update) { 624*48a46eb9SPierre Jolivet if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_fence(MPI_MODE_NOPUT | MPI_MODE_NOSUCCEED, *win)); 6259566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(array, laddr, sf->nroots * bytes)); 6265b0d146aSStefano Zampini } 6275b0d146aSStefano Zampini link->epoch = PETSC_FALSE; 6285b0d146aSStefano Zampini link->inuse = PETSC_FALSE; 6295b0d146aSStefano Zampini link->paddr = NULL; 6305b0d146aSStefano Zampini if (!reuse) { 6319566063dSJacob Faibussowitsch PetscCall(PetscFree(link->dyn_target_addr)); 6329566063dSJacob Faibussowitsch PetscCall(PetscFree(link->reqs)); 6339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&link->win)); 6349566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 63595fce210SBarry Smith *win = MPI_WIN_NULL; 6365b0d146aSStefano Zampini } 63795fce210SBarry Smith PetscFunctionReturn(0); 63895fce210SBarry Smith } 63995fce210SBarry Smith 6409371c9d4SSatish Balay static PetscErrorCode PetscSFSetUp_Window(PetscSF sf) { 64195fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 64295fce210SBarry Smith MPI_Group ingroup, outgroup; 64395fce210SBarry Smith 64495fce210SBarry Smith PetscFunctionBegin; 6459566063dSJacob Faibussowitsch PetscCall(PetscSFSetUpRanks(sf, MPI_GROUP_EMPTY)); 6465b0d146aSStefano Zampini if (!w->dynsf) { 6475b0d146aSStefano Zampini PetscInt i; 6485b0d146aSStefano Zampini PetscSFNode *remotes; 6495b0d146aSStefano Zampini 6509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sf->nranks, &remotes)); 6515b0d146aSStefano Zampini for (i = 0; i < sf->nranks; i++) { 6525b0d146aSStefano Zampini remotes[i].rank = sf->ranks[i]; 6535b0d146aSStefano Zampini remotes[i].index = 0; 6545b0d146aSStefano Zampini } 6559566063dSJacob Faibussowitsch PetscCall(PetscSFDuplicate(sf, PETSCSF_DUPLICATE_RANKS, &w->dynsf)); 6569566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(w->dynsf, PETSCSF_WINDOW_FLAVOR_CREATE)); /* break recursion */ 6579566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(w->dynsf, 1, sf->nranks, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 6589566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)sf, (PetscObject)w->dynsf)); 6595b0d146aSStefano Zampini } 66095fce210SBarry Smith switch (w->sync) { 6619371c9d4SSatish Balay case PETSCSF_WINDOW_SYNC_ACTIVE: PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup)); 6629371c9d4SSatish Balay default: break; 66395fce210SBarry Smith } 66495fce210SBarry Smith PetscFunctionReturn(0); 66595fce210SBarry Smith } 66695fce210SBarry Smith 6679371c9d4SSatish Balay static PetscErrorCode PetscSFSetFromOptions_Window(PetscSF sf, PetscOptionItems *PetscOptionsObject) { 66895fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 6695b0d146aSStefano Zampini PetscSFWindowFlavorType flavor = w->flavor; 67095fce210SBarry Smith 67195fce210SBarry Smith PetscFunctionBegin; 672d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "PetscSF Window options"); 6739566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_sync", "synchronization type to use for PetscSF Window communication", "PetscSFWindowSetSyncType", PetscSFWindowSyncTypes, (PetscEnum)w->sync, (PetscEnum *)&w->sync, NULL)); 6749566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-sf_window_flavor", "flavor to use for PetscSF Window creation", "PetscSFWindowSetFlavorType", PetscSFWindowFlavorTypes, (PetscEnum)flavor, (PetscEnum *)&flavor, NULL)); 6759566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(sf, flavor)); 676d0609cedSBarry Smith PetscOptionsHeadEnd(); 67795fce210SBarry Smith PetscFunctionReturn(0); 67895fce210SBarry Smith } 67995fce210SBarry Smith 6809371c9d4SSatish Balay static PetscErrorCode PetscSFReset_Window(PetscSF sf) { 68195fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 68295fce210SBarry Smith PetscSFDataLink link, next; 68395fce210SBarry Smith PetscSFWinLink wlink, wnext; 68495fce210SBarry Smith PetscInt i; 68595fce210SBarry Smith 68695fce210SBarry Smith PetscFunctionBegin; 68795fce210SBarry Smith for (link = w->link; link; link = next) { 68895fce210SBarry Smith next = link->next; 6899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->unit)); 69095fce210SBarry Smith for (i = 0; i < sf->nranks; i++) { 6919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->mine[i])); 6929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&link->remote[i])); 69395fce210SBarry Smith } 6949566063dSJacob Faibussowitsch PetscCall(PetscFree2(link->mine, link->remote)); 6959566063dSJacob Faibussowitsch PetscCall(PetscFree(link)); 69695fce210SBarry Smith } 69795fce210SBarry Smith w->link = NULL; 69895fce210SBarry Smith for (wlink = w->wins; wlink; wlink = wnext) { 69995fce210SBarry Smith wnext = wlink->next; 70028b400f6SJacob Faibussowitsch PetscCheck(!wlink->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_ARG_WRONGSTATE, "Window still in use with address %p", (void *)wlink->addr); 7019566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->dyn_target_addr)); 7029566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink->reqs)); 7039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_free(&wlink->win)); 7049566063dSJacob Faibussowitsch PetscCall(PetscFree(wlink)); 70595fce210SBarry Smith } 70695fce210SBarry Smith w->wins = NULL; 7079566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&w->dynsf)); 708*48a46eb9SPierre Jolivet if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info)); 70995fce210SBarry Smith PetscFunctionReturn(0); 71095fce210SBarry Smith } 71195fce210SBarry Smith 7129371c9d4SSatish Balay static PetscErrorCode PetscSFDestroy_Window(PetscSF sf) { 71395fce210SBarry Smith PetscFunctionBegin; 7149566063dSJacob Faibussowitsch PetscCall(PetscSFReset_Window(sf)); 7159566063dSJacob Faibussowitsch PetscCall(PetscFree(sf->data)); 7169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", NULL)); 7179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", NULL)); 7189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", NULL)); 7199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", NULL)); 7209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", NULL)); 7219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", NULL)); 72295fce210SBarry Smith PetscFunctionReturn(0); 72395fce210SBarry Smith } 72495fce210SBarry Smith 7259371c9d4SSatish Balay static PetscErrorCode PetscSFView_Window(PetscSF sf, PetscViewer viewer) { 72695fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 72795fce210SBarry Smith PetscBool iascii; 7285b0d146aSStefano Zampini PetscViewerFormat format; 72995fce210SBarry Smith 73095fce210SBarry Smith PetscFunctionBegin; 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 73395fce210SBarry Smith if (iascii) { 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current flavor=%s synchronization=%s MultiSF sort=%s\n", PetscSFWindowFlavorTypes[w->flavor], PetscSFWindowSyncTypes[w->sync], sf->rankorder ? "rank-order" : "unordered")); 7355b0d146aSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 7365b0d146aSStefano Zampini if (w->info != MPI_INFO_NULL) { 7375b0d146aSStefano Zampini PetscMPIInt k, nkeys; 7385b0d146aSStefano Zampini char key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL]; 7395b0d146aSStefano Zampini 7409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nkeys(w->info, &nkeys)); 7419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current info with %d keys. Ordered key-value pairs follow:\n", nkeys)); 7425b0d146aSStefano Zampini for (k = 0; k < nkeys; k++) { 7435b0d146aSStefano Zampini PetscMPIInt flag; 7445b0d146aSStefano Zampini 7459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get_nthkey(w->info, k, key)); 7469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Info_get(w->info, key, MPI_MAX_INFO_VAL, value, &flag)); 74728b400f6SJacob Faibussowitsch PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing key %s", key); 7489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s = %s\n", key, value)); 7495b0d146aSStefano Zampini } 7505b0d146aSStefano Zampini } else { 7519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " current info=MPI_INFO_NULL\n")); 7525b0d146aSStefano Zampini } 7535b0d146aSStefano Zampini } 75495fce210SBarry Smith } 75595fce210SBarry Smith PetscFunctionReturn(0); 75695fce210SBarry Smith } 75795fce210SBarry Smith 7589371c9d4SSatish Balay static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf, PetscSFDuplicateOption opt, PetscSF newsf) { 75995fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 76095fce210SBarry Smith PetscSFWindowSyncType synctype; 76195fce210SBarry Smith 76295fce210SBarry Smith PetscFunctionBegin; 76395fce210SBarry Smith synctype = w->sync; 76495fce210SBarry Smith /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */ 7655b0d146aSStefano Zampini if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK; 7669566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetSyncType(newsf, synctype)); 7679566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetFlavorType(newsf, w->flavor)); 7689566063dSJacob Faibussowitsch PetscCall(PetscSFWindowSetInfo(newsf, w->info)); 76995fce210SBarry Smith PetscFunctionReturn(0); 77095fce210SBarry Smith } 77195fce210SBarry Smith 7729371c9d4SSatish Balay static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, const void *rootdata, PetscMemType leafmtype, void *leafdata, MPI_Op op) { 77395fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 77495fce210SBarry Smith PetscInt i, nranks; 77595fce210SBarry Smith const PetscMPIInt *ranks; 7765b0d146aSStefano Zampini const MPI_Aint *target_disp; 77795fce210SBarry Smith const MPI_Datatype *mine, *remote; 778684a874aSStefano Zampini MPI_Request *reqs; 77995fce210SBarry Smith MPI_Win win; 78095fce210SBarry Smith 78195fce210SBarry Smith PetscFunctionBegin; 78208401ef6SPierre Jolivet PetscCheck(op == MPI_REPLACE, PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented"); 7839566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 7849566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote)); 7859566063dSJacob 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)); 78695fce210SBarry Smith for (i = 0; i < nranks; i++) { 7875b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 7885b0d146aSStefano Zampini 789684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 7909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win)); 791684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET) 7929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Rget(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win, &reqs[i])); 793684a874aSStefano Zampini #else 7949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win)); 795684a874aSStefano Zampini #endif 796684a874aSStefano Zampini } else { 7979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win)); 798684a874aSStefano Zampini } 79995fce210SBarry Smith } 80095fce210SBarry Smith PetscFunctionReturn(0); 80195fce210SBarry Smith } 80295fce210SBarry Smith 8039371c9d4SSatish Balay PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, void *leafdata, MPI_Op op) { 8045b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 80595fce210SBarry Smith MPI_Win win; 8064b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 80795fce210SBarry Smith 80895fce210SBarry Smith PetscFunctionBegin; 8099566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs)); 8109566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE)); 811684a874aSStefano Zampini if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { 812684a874aSStefano Zampini PetscInt i, nranks; 813684a874aSStefano Zampini const PetscMPIInt *ranks; 814684a874aSStefano Zampini 8159566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 816*48a46eb9SPierre Jolivet for (i = 0; i < nranks; i++) PetscCallMPI(MPI_Win_unlock(ranks[i], win)); 817684a874aSStefano Zampini } 8189566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf, unit, (void *)rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSTORE | MPI_MODE_NOSUCCEED, PETSC_FALSE, &win)); 81995fce210SBarry Smith PetscFunctionReturn(0); 82095fce210SBarry Smith } 82195fce210SBarry Smith 8229371c9d4SSatish Balay PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType leafmtype, const void *leafdata, PetscMemType rootmtype, void *rootdata, MPI_Op op) { 82395fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 82495fce210SBarry Smith PetscInt i, nranks; 82595fce210SBarry Smith const PetscMPIInt *ranks; 8265b0d146aSStefano Zampini const MPI_Aint *target_disp; 82795fce210SBarry Smith const MPI_Datatype *mine, *remote; 82895fce210SBarry Smith MPI_Win win; 82995fce210SBarry Smith 83095fce210SBarry Smith PetscFunctionBegin; 8319566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 8329566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote)); 8339566063dSJacob Faibussowitsch PetscCall(PetscSFWindowOpTranslate(&op)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win)); 83595fce210SBarry Smith for (i = 0; i < nranks; i++) { 8365b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 8375b0d146aSStefano Zampini 8389566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win)); 8399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win)); 8409566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win)); 84195fce210SBarry Smith } 84295fce210SBarry Smith PetscFunctionReturn(0); 84395fce210SBarry Smith } 84495fce210SBarry Smith 8459371c9d4SSatish Balay static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf, MPI_Datatype unit, const void *leafdata, void *rootdata, MPI_Op op) { 84695fce210SBarry Smith 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)); 8539566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win)); 85495fce210SBarry Smith PetscFunctionReturn(0); 85595fce210SBarry Smith } 8565b0d146aSStefano Zampini 8579371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, void *rootdata, PetscMemType leafmtype, const void *leafdata, void *leafupdate, MPI_Op op) { 85895fce210SBarry Smith PetscInt i, nranks; 85995fce210SBarry Smith const PetscMPIInt *ranks; 86095fce210SBarry Smith const MPI_Datatype *mine, *remote; 8615b0d146aSStefano Zampini const MPI_Aint *target_disp; 86295fce210SBarry Smith MPI_Win win; 8635b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 8645b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 8655b0d146aSStefano Zampini PetscSFWindowFlavorType oldf; 8665b0d146aSStefano Zampini #endif 86795fce210SBarry Smith 86895fce210SBarry Smith PetscFunctionBegin; 8699566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL)); 8709566063dSJacob Faibussowitsch PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote)); 8719566063dSJacob Faibussowitsch PetscCall(PetscSFWindowOpTranslate(&op)); 8725b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 8735b0d146aSStefano Zampini /* FetchAndOp without MPI_Get_Accumulate requires locking. 8745b0d146aSStefano Zampini we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */ 8755b0d146aSStefano Zampini oldf = w->flavor; 8765b0d146aSStefano Zampini w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE; 8779566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, 0, 0, &target_disp, NULL, &win)); 8785b0d146aSStefano Zampini #else 8799566063dSJacob Faibussowitsch PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win)); 8805b0d146aSStefano Zampini #endif 8815b0d146aSStefano Zampini for (i = 0; i < nranks; i++) { 8825b0d146aSStefano Zampini MPI_Aint tdp = target_disp ? target_disp[i] : 0; 8835b0d146aSStefano Zampini 8845b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 8859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, ranks[i], 0, win)); 8869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get(leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], win)); 8879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win)); 8889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Win_unlock(ranks[i], win)); 8895b0d146aSStefano Zampini #else 8909566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], 0, win)); 8919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Get_accumulate((void *)leafdata, 1, mine[i], leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win)); 8929566063dSJacob Faibussowitsch if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win)); 8935b0d146aSStefano Zampini #endif 8945b0d146aSStefano Zampini } 8955b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 8965b0d146aSStefano Zampini w->flavor = oldf; 8975b0d146aSStefano Zampini #endif 89895fce210SBarry Smith PetscFunctionReturn(0); 89995fce210SBarry Smith } 90095fce210SBarry Smith 9019371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf, MPI_Datatype unit, void *rootdata, const void *leafdata, void *leafupdate, MPI_Op op) { 90295fce210SBarry Smith MPI_Win win; 9035b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9045b0d146aSStefano Zampini PetscSF_Window *w = (PetscSF_Window *)sf->data; 9055b0d146aSStefano Zampini #endif 9064b9acda6SJunchao Zhang MPI_Request *reqs = NULL; 90795fce210SBarry Smith 90895fce210SBarry Smith PetscFunctionBegin; 9099566063dSJacob Faibussowitsch PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs)); 9109566063dSJacob Faibussowitsch if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE)); 9115b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE) 9129566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win)); 9135b0d146aSStefano Zampini #else 9149566063dSJacob Faibussowitsch PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, PETSC_TRUE, &win)); 9155b0d146aSStefano Zampini #endif 91695fce210SBarry Smith PetscFunctionReturn(0); 91795fce210SBarry Smith } 91895fce210SBarry Smith 9199371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf) { 92095fce210SBarry Smith PetscSF_Window *w = (PetscSF_Window *)sf->data; 92195fce210SBarry Smith 92295fce210SBarry Smith PetscFunctionBegin; 92395fce210SBarry Smith sf->ops->SetUp = PetscSFSetUp_Window; 92495fce210SBarry Smith sf->ops->SetFromOptions = PetscSFSetFromOptions_Window; 92595fce210SBarry Smith sf->ops->Reset = PetscSFReset_Window; 92695fce210SBarry Smith sf->ops->Destroy = PetscSFDestroy_Window; 92795fce210SBarry Smith sf->ops->View = PetscSFView_Window; 92895fce210SBarry Smith sf->ops->Duplicate = PetscSFDuplicate_Window; 929ad227feaSJunchao Zhang sf->ops->BcastBegin = PetscSFBcastBegin_Window; 930ad227feaSJunchao Zhang sf->ops->BcastEnd = PetscSFBcastEnd_Window; 93195fce210SBarry Smith sf->ops->ReduceBegin = PetscSFReduceBegin_Window; 93295fce210SBarry Smith sf->ops->ReduceEnd = PetscSFReduceEnd_Window; 93395fce210SBarry Smith sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window; 93495fce210SBarry Smith sf->ops->FetchAndOpEnd = PetscSFFetchAndOpEnd_Window; 93595fce210SBarry Smith 9369566063dSJacob Faibussowitsch PetscCall(PetscNewLog(sf, &w)); 93795fce210SBarry Smith sf->data = (void *)w; 93895fce210SBarry Smith w->sync = PETSCSF_WINDOW_SYNC_FENCE; 9395b0d146aSStefano Zampini w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE; 9405b0d146aSStefano Zampini w->info = MPI_INFO_NULL; 94195fce210SBarry Smith 9429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", PetscSFWindowSetSyncType_Window)); 9439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", PetscSFWindowGetSyncType_Window)); 9449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", PetscSFWindowSetFlavorType_Window)); 9459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", PetscSFWindowGetFlavorType_Window)); 9469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", PetscSFWindowSetInfo_Window)); 9479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", PetscSFWindowGetInfo_Window)); 94895fce210SBarry Smith 94995fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6)) 95095fce210SBarry Smith { 95195fce210SBarry Smith PetscBool ackbug = PETSC_FALSE; 9529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-acknowledge_ompi_onesided_bug", &ackbug, NULL)); 95395fce210SBarry Smith if (ackbug) { 9549566063dSJacob Faibussowitsch PetscCall(PetscInfo(sf, "Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n")); 95595fce210SBarry 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"); 95695fce210SBarry Smith } 95795fce210SBarry Smith #endif 95895fce210SBarry Smith PetscFunctionReturn(0); 95995fce210SBarry Smith } 960