PetaVision  Alpha
HyPerDeliveryFacade.cpp
1 /*
2  * HyPerDeliveryFacade.cpp
3  *
4  * Created on: Aug 24, 2017
5  * Author: Pete Schultz
6  */
7 
8 #include "HyPerDeliveryFacade.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include "utils/MapLookupByType.hpp"
11 
12 namespace PV {
13 
14 HyPerDeliveryFacade::HyPerDeliveryFacade(char const *name, HyPerCol *hc) { initialize(name, hc); }
15 
16 HyPerDeliveryFacade::HyPerDeliveryFacade() {}
17 
18 HyPerDeliveryFacade::~HyPerDeliveryFacade() {
19  delete mDeliveryIntern;
20 }
21 
22 int HyPerDeliveryFacade::initialize(char const *name, HyPerCol *hc) {
23  return BaseDelivery::initialize(name, hc);
24 }
25 
26 void HyPerDeliveryFacade::setObjectType() { mObjectType = "HyPerDeliveryFacade"; }
27 
28 int HyPerDeliveryFacade::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
29  int status = BaseDelivery::ioParamsFillGroup(ioFlag);
30  ioParam_accumulateType(ioFlag);
32  if (ioFlag == PARAMS_IO_READ) {
33  createDeliveryIntern();
34  }
35  if (mDeliveryIntern) {
36  mDeliveryIntern->ioParams(ioFlag, false, false);
37  }
38  return status;
39 }
40 
41 void HyPerDeliveryFacade::ioParam_accumulateType(enum ParamsIOFlag ioFlag) {
42  parent->parameters()->ioParamString(
43  ioFlag, name, "pvpatchAccumulateType", &mAccumulateTypeString, "convolve");
44  if (ioFlag == PARAMS_IO_READ) {
45  pvAssert(mAccumulateTypeString and mAccumulateTypeString[0]);
46  // Convert string to lowercase so that capitalization doesn't matter.
47  for (char *c = mAccumulateTypeString; *c != '\0'; c++) {
48  *c = (char)tolower((int)*c);
49  }
50 
51  if (strcmp(mAccumulateTypeString, "convolve") == 0) {
52  mAccumulateType = HyPerDelivery::CONVOLVE;
53  }
54  else if (strcmp(mAccumulateTypeString, "stochastic") == 0) {
55  mAccumulateType = HyPerDelivery::STOCHASTIC;
56  }
57  else {
58  if (parent->getCommunicator()->globalCommRank() == 0) {
59  ErrorLog().printf(
60  "%s error: pvpatchAccumulateType \"%s\" is unrecognized.\n",
61  getDescription_c(),
62  mAccumulateTypeString);
63  ErrorLog().printf(" Allowed values are \"convolve\" or \"stochastic\".\n");
64  }
65  MPI_Barrier(parent->getCommunicator()->globalCommunicator());
66  exit(EXIT_FAILURE);
67  }
68  }
69  pvAssert(!parent->parameters()->presentAndNotBeenRead(name, "receiveGpu"));
70  FatalIf(
71  mReceiveGpu and mAccumulateType == HyPerDelivery::STOCHASTIC,
72  "%s sets receiveGpu to true and pvpatchAccumulateType to stochastic, "
73  "but stochastic release has not been implemented on the GPU.\n",
74  getDescription_c());
75 }
76 
78  parent->parameters()->ioParamValue(
79  ioFlag,
80  name,
81  "updateGSynFromPostPerspective",
82  &mUpdateGSynFromPostPerspective,
83  mUpdateGSynFromPostPerspective);
84 }
85 
86 void HyPerDeliveryFacade::createDeliveryIntern() {
87  // Check channel number for noupdate
88  if (getChannelCode() == CHANNEL_NOUPDATE) {
89  mDeliveryIntern = nullptr;
90  return;
91  }
92  BaseObject *baseObject = nullptr;
93  if (getReceiveGpu()) {
94 #ifdef PV_USE_CUDA
95  if (getUpdateGSynFromPostPerspective()) {
96  baseObject = Factory::instance()->createByKeyword(
97  "PostsynapticPerspectiveGPUDelivery", name, parent);
98  }
99  else {
100  baseObject = Factory::instance()->createByKeyword(
101  "PresynapticPerspectiveGPUDelivery", name, parent);
102  }
103 #else //
104  pvAssert(0); // If PV_USE_CUDA is off, receiveGpu should always be false.
105 #endif // PV_USE_CUDA
106  }
107  else {
108  switch (mAccumulateType) {
109  case HyPerDelivery::CONVOLVE:
110  if (getUpdateGSynFromPostPerspective()) {
111  baseObject = Factory::instance()->createByKeyword(
112  "PostsynapticPerspectiveConvolveDelivery", name, parent);
113  }
114  else {
115  baseObject = Factory::instance()->createByKeyword(
116  "PresynapticPerspectiveConvolveDelivery", name, parent);
117  }
118  break;
119  case HyPerDelivery::STOCHASTIC:
120  if (getUpdateGSynFromPostPerspective()) {
121  baseObject = Factory::instance()->createByKeyword(
122  "PostsynapticPerspectiveStochasticDelivery", name, parent);
123  }
124  else {
125  baseObject = Factory::instance()->createByKeyword(
126  "PresynapticPerspectiveStochasticDelivery", name, parent);
127  }
128  break;
129  default:
130  pvAssert(0); // CONVOLVE and STOCHASTIC are the only allowed possibilities
131  break;
132  }
133  }
134  if (baseObject != nullptr) {
135  mDeliveryIntern = dynamic_cast<HyPerDelivery *>(baseObject);
136  pvAssert(mDeliveryIntern);
137  }
138 }
139 
140 Response::Status HyPerDeliveryFacade::communicateInitInfo(
141  std::shared_ptr<CommunicateInitInfoMessage const> message) {
142  auto status = BaseDelivery::communicateInitInfo(message);
143  if (!Response::completed(status)) {
144  return status;
145  }
146 
147  // DeliveryIntern needs to know the ConnectionData and the WeightsPair.
148  if (mDeliveryIntern) {
149  Response::Status internStatus = mDeliveryIntern->respond(message);
150  if (internStatus == Response::POSTPONE) {
151  return Response::POSTPONE;
152  }
153 #ifdef PV_USE_CUDA
154  mUsingGPUFlag = mDeliveryIntern->isUsingGPU();
155 #endif // PV_USE_CUDA
156  }
157 
158  return Response::SUCCESS;
159 }
160 
161 #ifdef PV_USE_CUDA
162 Response::Status
163 HyPerDeliveryFacade::setCudaDevice(std::shared_ptr<SetCudaDeviceMessage const> message) {
164  auto status = BaseDelivery::setCudaDevice(message);
165  if (status != Response::SUCCESS) {
166  return status;
167  }
168  if (mDeliveryIntern) {
169  status = mDeliveryIntern->respond(message);
170  }
171  return status;
172 }
173 #endif // PV_USE_CUDA
174 
175 Response::Status HyPerDeliveryFacade::allocateDataStructures() {
176  auto status = BaseDelivery::allocateDataStructures();
177  if (Response::completed(status) and mDeliveryIntern != nullptr) {
178  auto internMessage = std::make_shared<AllocateDataMessage>();
179  status = mDeliveryIntern->respond(internMessage);
180  }
181  return status;
182 }
183 
184 void HyPerDeliveryFacade::deliver() {
185  if (mDeliveryIntern) {
186  mDeliveryIntern->deliver();
187  }
188 }
189 
190 void HyPerDeliveryFacade::deliverUnitInput(float *recvBuffer) {
191  if (mDeliveryIntern) {
192  mDeliveryIntern->deliverUnitInput(recvBuffer);
193  }
194 }
195 
197  return getChannelCode() == CHANNEL_NOUPDATE ? true : mDeliveryIntern->isAllInputReady();
198 }
199 
200 } // end namespace PV
virtual bool isAllInputReady() override
bool isUsingGPU() const
Definition: BaseObject.hpp:116
virtual void ioParam_updateGSynFromPostPerspective(enum ParamsIOFlag ioFlag)
updateGSynFromPostPerspective: Specifies if the connection should push from pre or pull from post...
virtual void ioParam_accumulateType(enum ParamsIOFlag ioFlag)
pvpatchAccumulateType: Specifies the method to accumulate synaptic input
static bool completed(Status &a)
Definition: Response.hpp:49
virtual bool isAllInputReady() override
void ioParams(enum ParamsIOFlag ioFlag, bool printHeader, bool printFooter)
Definition: BaseObject.cpp:74
int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override