PetaVision  Alpha
IdentDelivery.cpp
1 /*
2  * IdentDelivery.cpp
3  *
4  * Created on: Aug 24, 2017
5  * Author: Pete Schultz
6  */
7 
8 #include "IdentDelivery.hpp"
9 #include "columns/HyPerCol.hpp"
10 #include "utils/MapLookupByType.hpp"
11 #include <cstring>
12 
13 namespace PV {
14 
15 IdentDelivery::IdentDelivery(char const *name, HyPerCol *hc) { initialize(name, hc); }
16 
17 int IdentDelivery::initialize(char const *name, HyPerCol *hc) {
18  return BaseDelivery::initialize(name, hc);
19 }
20 
21 void IdentDelivery::setObjectType() { mObjectType = "IdentDelivery"; }
22 
23 void IdentDelivery::ioParam_receiveGpu(enum ParamsIOFlag ioFlag) {
24  // Never receive from gpu
25  mReceiveGpu = false;
26  if (ioFlag == PARAMS_IO_READ) {
27  parent->parameters()->handleUnnecessaryParameter(name, "receiveGpu", false /*correctValue*/);
28  }
29 }
30 
31 Response::Status
32 IdentDelivery::communicateInitInfo(std::shared_ptr<CommunicateInitInfoMessage const> message) {
33  auto status = BaseDelivery::communicateInitInfo(message);
34  if (status != Response::SUCCESS) {
35  return status;
36  }
37 
38  mSingleArbor = mapLookupByType<SingleArbor>(message->mHierarchy, getDescription());
39  FatalIf(!mSingleArbor, "%s requires a SingleArbor component.\n", getDescription_c());
40 
41  checkPreAndPostDimensions();
42  return Response::SUCCESS;
43 }
44 
45 void IdentDelivery::checkPreAndPostDimensions() {
46  int status = PV_SUCCESS;
47  pvAssert(mPreLayer and mPostLayer); // Only call this after BaseDelivery::communicateInitInfo().
48  PVLayerLoc const *preLoc = mPreLayer->getLayerLoc();
49  PVLayerLoc const *postLoc = mPostLayer->getLayerLoc();
50  if (preLoc->nx != postLoc->nx) {
51  ErrorLog().printf(
52  "%s requires pre and post nx be equal (%d versus %d).\n",
53  getDescription_c(),
54  preLoc->nx,
55  postLoc->nx);
56  status = PV_FAILURE;
57  }
58  if (preLoc->ny != postLoc->ny) {
59  ErrorLog().printf(
60  "%s requires pre and post ny be equal (%d versus %d).\n",
61  getDescription_c(),
62  preLoc->ny,
63  postLoc->ny);
64  status = PV_FAILURE;
65  }
66  if (preLoc->nf != postLoc->nf) {
67  ErrorLog().printf(
68  "%s requires pre and post nf be equal (%d versus %d).\n",
69  getDescription_c(),
70  preLoc->nf,
71  postLoc->nf);
72  status = PV_FAILURE;
73  }
74  if (preLoc->nbatch != postLoc->nbatch) {
75  ErrorLog().printf(
76  "%s requires pre and post nbatch be equal (%d versus %d).\n",
77  getDescription_c(),
78  preLoc->nbatch,
79  postLoc->nbatch);
80  status = PV_FAILURE;
81  }
82  FatalIf(
83  status != PV_SUCCESS,
84  "IdentDelivery \"%s\" Error: %s and %s do not have the same dimensions.\n Dims: "
85  "%dx%dx%d vs. %dx%dx%d\n",
86  name,
87  mPreLayer->getName(),
88  mPostLayer->getName(),
89  preLoc->nx,
90  preLoc->ny,
91  preLoc->nf,
92  postLoc->nx,
93  postLoc->ny,
94  postLoc->nf);
95 }
96 
97 void IdentDelivery::deliver() {
98  if (mChannelCode == CHANNEL_NOUPDATE) {
99  return;
100  }
101 
102  int delay = mSingleArbor->getDelay(0);
103  PVLayerCube const preActivityCube = mPreLayer->getPublisher()->createCube(delay);
104  PVLayerLoc const &preLoc = preActivityCube.loc;
105  PVLayerLoc const &postLoc = *mPostLayer->getLayerLoc();
106 
107  int const nx = preLoc.nx;
108  int const ny = preLoc.ny;
109  int const nf = preLoc.nf;
110  int nxPreExtended = nx + preLoc.halo.lt + preLoc.halo.rt;
111  int nyPreExtended = ny + preLoc.halo.dn + preLoc.halo.up;
112  int numPreExtended = nxPreExtended * nyPreExtended * nf;
113  pvAssert(numPreExtended * preLoc.nbatch == preActivityCube.numItems);
114  int numPostRestricted = nx * ny * nf;
115 
116  float *postChannel = mPostLayer->getChannel(mChannelCode);
117  for (int b = 0; b < parent->getNBatch(); b++) {
118  float const *preActivityBuffer = preActivityCube.data + b * numPreExtended;
119  float *postGSynBuffer = postChannel + b * numPostRestricted;
120  if (preActivityCube.isSparse) {
121  SparseList<float>::Entry const *activeIndices =
122  (SparseList<float>::Entry *)preActivityCube.activeIndices + b * numPreExtended;
123  int numActive = preActivityCube.numActive[b];
124 #ifdef PV_USE_OPENMP_THREADS
125 #pragma omp parallel for
126 #endif
127  for (int loopIndex = 0; loopIndex < numActive; loopIndex++) {
128  int kPre = activeIndices[loopIndex].index;
129  int kx = kxPos(kPre, nxPreExtended, nyPreExtended, nf) - preLoc.halo.lt;
130  int ky = kyPos(kPre, nxPreExtended, nyPreExtended, nf) - preLoc.halo.up;
131  if (kx < 0 or kx >= nx or ky < 0 or ky >= ny) {
132  continue;
133  }
134  int kf = featureIndex(kPre, nxPreExtended, nyPreExtended, nf);
135  int kPost = kIndex(kx, ky, kf, nx, ny, nf);
136  pvAssert(kPost >= 0 and kPost < numPostRestricted);
137  float a = activeIndices[loopIndex].value;
138  postGSynBuffer[kPost] += a;
139  }
140  }
141  else {
142  int const nk = postLoc.nx * postLoc.nf;
143 #ifdef PV_USE_OPENMP_THREADS
144 #pragma omp parallel for
145 #endif
146  for (int y = 0; y < ny; y++) {
147  int preLineIndex =
148  kIndex(preLoc.halo.lt, y + preLoc.halo.up, 0, nxPreExtended, nyPreExtended, nf);
149 
150  float const *preActivityLine = &preActivityBuffer[preLineIndex];
151  int postLineIndex = kIndex(0, y, 0, postLoc.nx, ny, postLoc.nf);
152  float *postGSynLine = &postGSynBuffer[postLineIndex];
153  for (int k = 0; k < nk; k++) {
154  postGSynLine[k] += preActivityLine[k];
155  }
156  }
157  }
158  }
159 #ifdef PV_USE_CUDA
160  mPostLayer->setUpdatedDeviceGSynFlag(!mReceiveGpu);
161 #endif // PV_USE_CUDA
162 }
163 
164 void IdentDelivery::deliverUnitInput(float *recvBuffer) {
165  const int numNeuronsPost = mPostLayer->getNumNeuronsAllBatches();
166 #ifdef PV_USE_OPENMP_THREADS
167 #pragma omp parallel for
168 #endif
169  for (int k = 0; k < numNeuronsPost; k++) {
170  recvBuffer[k] += 1.0f;
171  }
172 }
173 
175  bool isReady;
176  if (getChannelCode() == CHANNEL_NOUPDATE) {
177  isReady = true;
178  }
179  else {
180  isReady = getPreLayer()->isExchangeFinished(mSingleArbor->getDelay(0));
181  }
182  return isReady;
183 }
184 
185 } // end namespace PV
virtual void ioParam_receiveGpu(enum ParamsIOFlag ioFlag) override
IdentDeliver does not use the GPU. It is an error to set receiveGpu to true.
PVLayerCube createCube(int delay=0)
Definition: Publisher.cpp:60
bool isExchangeFinished(int delay=0)
virtual bool isAllInputReady() override