1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
/*=========================================================================
Program: Visualization Toolkit
Module: MPIController.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <mpi.h>
#include "vtkMPIController.h"
#include "vtkProcessGroup.h"
#include "ExerciseMultiProcessController.h"
#include "vtkSmartPointer.h"
#define VTK_CREATE(type, name) \
vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
namespace
{
int mpiTag = 5678;
int data = -1;
}
// returns 0 for success
int CheckNoBlockSends(vtkMPIController* controller)
{
int retVal = 0;
// processes send their rank to the next, higher ranked process
int myRank = controller->GetLocalProcessId();
int numRanks = controller->GetNumberOfProcesses();
vtkMPICommunicator::Request sendRequest;
data = myRank;
if(myRank != numRanks - 1)
{
if(controller->NoBlockSend(&data, 1, myRank+1, mpiTag, sendRequest) == 0)
{
vtkGenericWarningMacro("Problem with NoBlockSend.");
retVal = 1;
}
}
return retVal;
}
// returns 0 for success
int CheckNoBlockRecvs(vtkMPIController* controller, int sendSource,
int wasMessageSent, const char* info)
{
int myRank = controller->GetLocalProcessId();
int retVal = 0;
if(myRank)
{
int flag = -1, actualSource = -1, size = -1;
if(controller->Iprobe(sendSource, mpiTag, &flag, &actualSource,
&size, &size) == 0)
{
vtkGenericWarningMacro("Problem with Iprobe " << info);
retVal = 1;
}
if(flag != wasMessageSent)
{
if(wasMessageSent)
{
vtkGenericWarningMacro("Did not receive the message yet but should have " << info);
}
else
{
vtkGenericWarningMacro(" Received a message I shouldn't have " << info);
}
retVal = 1;
}
if(wasMessageSent == 0)
{ // no message sent so no need to check if we can receive it
return retVal;
}
else
{
if(actualSource != myRank-1)
{
vtkGenericWarningMacro("Did not receive the proper source id " << info);
retVal = 1;
}
if(size != 1)
{
vtkGenericWarningMacro("Did not receive the proper size " << info);
retVal = 1;
}
}
int recvData = -1;
vtkMPICommunicator::Request recvRequest;
if(controller->NoBlockReceive(&recvData, 1, sendSource, mpiTag, recvRequest) == 0)
{
vtkGenericWarningMacro("Problem with NoBlockReceive " << info);
retVal = 1;
}
recvRequest.Wait();
if(recvData != myRank - 1)
{
vtkGenericWarningMacro("Did not receive the proper information " << info);
retVal = 1;
}
}
return retVal;
}
// returns 0 for success
int ExerciseNoBlockCommunications(vtkMPIController* controller)
{
if(controller->GetNumberOfProcesses() == 1)
{
return 0;
}
int retVal = CheckNoBlockRecvs(
controller, vtkMultiProcessController::ANY_SOURCE, 0, "case 1");
// barrier to make sure there's really no message to receive
controller->Barrier();
retVal = retVal | CheckNoBlockSends(controller);
// barrier to make sure it's really a non-blocking send
controller->Barrier();
int myRank = controller->GetLocalProcessId();
retVal = retVal | CheckNoBlockRecvs(controller, myRank - 1, 1, "case 2");
// do it again with doing an any_source receive
controller->Barrier();
retVal = retVal | CheckNoBlockSends(controller);
// barrier to make sure it's really a non-blocking send
controller->Barrier();
retVal = retVal | CheckNoBlockRecvs(
controller, vtkMultiProcessController::ANY_SOURCE, 1, "case 3");
return retVal;
}
int MPIController(int argc, char* argv[])
{
// This is here to avoid false leak messages from vtkDebugLeaks when
// using mpich. It appears that the root process which spawns all the
// main processes waits in MPI_Init() and calls exit() when
// the others are done, causing apparent memory leaks for any objects
// created before MPI_Init().
MPI_Init(&argc, &argv);
VTK_CREATE(vtkMPIController, controller);
controller->Initialize(&argc, &argv, 1);
int retval = ExerciseMultiProcessController(controller);
retval = retval | ExerciseNoBlockCommunications(controller);
// The previous run of ExerciseMultiProcessController used the native MPI
// collective operations. There is also a second (inefficient) implementation
// of these within the base vtkCommunicator class. This hack should force the
// class to use the VTK implementation. In practice, the collective
// operations will probably never be used like this, but this is a convenient
// place to test for completeness.
VTK_CREATE(vtkProcessGroup, group);
group->Initialize(controller);
vtkSmartPointer<vtkMultiProcessController> genericController;
genericController.TakeReference(
controller->vtkMultiProcessController::CreateSubController(group));
if (!retval)
{
retval = ExerciseMultiProcessController(genericController);
}
controller->Finalize();
return retval;
}
|