PetaVision  Alpha
MomentumLCALayer.cpp
1 /*
2  * MomentumLCALayer.cpp
3  *
4  * Created on: Mar 15, 2016
5  * Author: slundquist
6  */
7 
8 #include "MomentumLCALayer.hpp"
9 #include <iostream>
10 
11 #ifdef PV_USE_CUDA
12 
13 #include "../cudakernels/CudaUpdateStateFunctions.hpp"
14 
15 #endif
16 
17 void MomentumLCALayer_update_state(
18  const int nbatch,
19  const int numNeurons,
20  const int nx,
21  const int ny,
22  const int nf,
23  const int lt,
24  const int rt,
25  const int dn,
26  const int up,
27  const int numChannels,
28  float *V,
29  int numVertices,
30  float *verticesV,
31  float *verticesA,
32  float *slopes,
33  const bool selfInteract,
34  double *dtAdapt,
35  const float tau,
36  const float LCAMomentumRate,
37  float *GSynHead,
38  float *activity,
39  float *prevDrive);
40 
41 namespace PV {
42 
43 MomentumLCALayer::MomentumLCALayer() { initialize_base(); }
44 
45 MomentumLCALayer::MomentumLCALayer(const char *name, HyPerCol *hc) {
46  initialize_base();
47  initialize(name, hc);
48 }
49 
50 MomentumLCALayer::~MomentumLCALayer() {}
51 
52 int MomentumLCALayer::initialize_base() {
53  numChannels = 1; // If a connection connects to this layer on inhibitory channel,
54  // HyPerLayer::requireChannel will add necessary channel
55  timeConstantTau = 1.0;
56  LCAMomentumRate = 0;
57  // Locality in conn
58  selfInteract = true;
59  return PV_SUCCESS;
60 }
61 
62 int MomentumLCALayer::initialize(const char *name, HyPerCol *hc) {
63  HyPerLCALayer::initialize(name, hc);
64 
65  return PV_SUCCESS;
66 }
67 
68 Response::Status MomentumLCALayer::allocateDataStructures() {
69  auto status = HyPerLCALayer::allocateDataStructures();
70  allocateRestrictedBuffer(&prevDrive, "prevDrive of LCA layer");
71 
72  // Initialize buffer to 0
73  for (int i = 0; i < getNumNeuronsAllBatches(); i++) {
74  prevDrive[i] = 0;
75  }
76 
77 #ifdef PV_USE_CUDA
78  if (mUpdateGpu) {
79  d_prevDrive->copyToDevice(prevDrive);
80  }
81 #endif
82 
83  return status;
84 }
85 
86 int MomentumLCALayer::ioParamsFillGroup(enum ParamsIOFlag ioFlag) {
87  int status = HyPerLCALayer::ioParamsFillGroup(ioFlag);
88  ioParam_LCAMomentumRate(ioFlag);
89 
90  return status;
91 }
92 
93 void MomentumLCALayer::ioParam_LCAMomentumRate(enum ParamsIOFlag ioFlag) {
94  parent->parameters()->ioParamValue(
95  ioFlag, name, "LCAMomentumRate", &LCAMomentumRate, LCAMomentumRate, true /*warnIfAbsent*/);
96 }
97 
98 #ifdef PV_USE_CUDA
99 int MomentumLCALayer::allocateUpdateKernel() {
100  PVCuda::CudaDevice *device = parent->getDevice();
101  d_prevDrive = device->createBuffer(getNumNeuronsAllBatches() * sizeof(float), &description);
102  // Set to temp pointer of the subclass
103  PVCuda::CudaUpdateMomentumLCALayer *updateKernel =
105  // Set arguments
106  const PVLayerLoc *loc = getLayerLoc();
107  const int nx = loc->nx;
108  const int ny = loc->ny;
109  const int nf = loc->nf;
110  const int num_neurons = nx * ny * nf;
111  const int nbatch = loc->nbatch;
112  const int lt = loc->halo.lt;
113  const int rt = loc->halo.rt;
114  const int dn = loc->halo.dn;
115  const int up = loc->halo.up;
116  const int numChannels = this->numChannels;
117  PVCuda::CudaBuffer *d_V = getDeviceV();
118  assert(d_V);
119  assert(d_prevDrive);
120  const float Vth = this->VThresh;
121  const float AMax = this->AMax;
122  const float AMin = this->AMin;
123  const float AShift = this->AShift;
124  const float VWidth = this->VWidth;
125  const bool selfInteract = this->selfInteract;
126  const float tau = timeConstantTau
127  / (float)parent->getDeltaTime(); // TODO: eliminate need to call parent method
128  PVCuda::CudaBuffer *d_GSyn = getDeviceGSyn();
129  PVCuda::CudaBuffer *d_activity = getDeviceActivity();
130 
131  size_t size = parent->getNBatch() * sizeof(double);
132  d_dtAdapt = device->createBuffer(size, &description);
133 
134  size = (size_t)numVertices * sizeof(*verticesV);
135  d_verticesV = device->createBuffer(size, &description);
136  d_verticesA = device->createBuffer(size, &description);
137  d_slopes = device->createBuffer(size + sizeof(*slopes), &description);
138 
139  d_verticesV->copyToDevice(verticesV);
140  d_verticesA->copyToDevice(verticesA);
141  d_slopes->copyToDevice(slopes);
142 
143  // Set arguments to kernel
144  updateKernel->setArgs(
145  nbatch,
146  num_neurons,
147  nx,
148  ny,
149  nf,
150  lt,
151  rt,
152  dn,
153  up,
154  numChannels,
155  d_V,
156  d_prevDrive,
157  numVertices,
158  d_verticesV,
159  d_verticesA,
160  d_slopes,
161  selfInteract,
162  d_dtAdapt,
163  tau,
164  LCAMomentumRate,
165  d_GSyn,
166  d_activity);
167 
168  // Update d_V for V initialization
169 
170  // set updateKernel to krUpdate
171  krUpdate = updateKernel;
172  return PV_SUCCESS;
173 }
174 
175 Response::Status MomentumLCALayer::updateStateGpu(double time, double dt) {
176  if (triggerLayer != NULL) {
177  Fatal().printf("HyPerLayer::Trigger reset of V does not work on GPUs\n");
178  }
179  // Copy over d_dtAdapt
180  d_dtAdapt->copyToDevice(deltaTimes());
181 
182  // Change dt to match what is passed in
183  PVCuda::CudaUpdateMomentumLCALayer *updateKernel =
184  dynamic_cast<PVCuda::CudaUpdateMomentumLCALayer *>(krUpdate);
185  assert(updateKernel);
186  runUpdateKernel();
187 
188  return Response::SUCCESS;
189 }
190 #endif
191 
192 Response::Status MomentumLCALayer::updateState(double time, double dt) {
193  const PVLayerLoc *loc = getLayerLoc();
194  float *A = clayer->activity->data;
195  float *V = getV();
196  int num_channels = getNumChannels();
197  float *gSynHead = GSyn == NULL ? NULL : GSyn[0];
198  int nx = loc->nx;
199  int ny = loc->ny;
200  int nf = loc->nf;
201  int num_neurons = nx * ny * nf;
202  int nbatch = loc->nbatch;
203  // Only update when the probe updates
204 
205  MomentumLCALayer_update_state(
206  nbatch,
207  num_neurons,
208  nx,
209  ny,
210  nf,
211  loc->halo.lt,
212  loc->halo.rt,
213  loc->halo.dn,
214  loc->halo.up,
215  numChannels,
216  V,
217  numVertices,
218  verticesV,
219  verticesA,
220  slopes,
221  selfInteract,
222  deltaTimes(),
223  timeConstantTau / (float)dt,
224  LCAMomentumRate,
225  gSynHead,
226  A,
227  prevDrive);
228  return Response::SUCCESS;
229 }
230 
231 Response::Status MomentumLCALayer::registerData(Checkpointer *checkpointer) {
232  auto status = HyPerLCALayer::registerData(checkpointer);
233  if (!Response::completed(status)) {
234  return status;
235  }
236  checkpointPvpActivityFloat(checkpointer, "prevDrive", prevDrive, false /*not extended*/);
237  return Response::SUCCESS;
238 }
239 
240 Response::Status MomentumLCALayer::processCheckpointRead() {
241  auto status = HyPerLCALayer::processCheckpointRead();
242  if (!Response::completed(status)) {
243  return status;
244  }
245 #ifdef PV_USE_CUDA
246  // Copy prevDrive onto GPU
247  if (mUpdateGpu) {
248  d_prevDrive->copyToDevice(prevDrive);
249  parent->getDevice()->syncDevice();
250  return Response::SUCCESS;
251  }
252  else {
253  return Response::NO_ACTION;
254  }
255 #else
256  return Response::NO_ACTION;
257 #endif
258 }
259 
260 Response::Status MomentumLCALayer::prepareCheckpointWrite() {
261 #ifdef PV_USE_CUDA
262  // Copy prevDrive from GPU
263  if (mUpdateGpu) {
264  d_prevDrive->copyFromDevice(prevDrive);
265  parent->getDevice()->syncDevice();
266  return Response::SUCCESS;
267  }
268  else {
269  return Response::NO_ACTION;
270  }
271 #else
272  return Response::NO_ACTION;
273 #endif
274 }
275 
276 } // end namespace PV
277 
278 void MomentumLCALayer_update_state(
279  const int nbatch,
280  const int numNeurons,
281  const int nx,
282  const int ny,
283  const int nf,
284  const int lt,
285  const int rt,
286  const int dn,
287  const int up,
288  const int numChannels,
289 
290  float *V,
291  int numVertices,
292  float *verticesV,
293  float *verticesA,
294  float *slopes,
295  const bool selfInteract,
296  double *dtAdapt,
297  const float tau,
298  const float LCAMomentumRate,
299  float *GSynHead,
300  float *activity,
301  float *prevDrive) {
302  updateV_MomentumLCALayer(
303  nbatch,
304  numNeurons,
305  numChannels,
306  V,
307  GSynHead,
308  activity,
309  prevDrive,
310  numVertices,
311  verticesV,
312  verticesA,
313  slopes,
314  dtAdapt,
315  tau,
316  LCAMomentumRate,
317  selfInteract,
318  nx,
319  ny,
320  nf,
321  lt,
322  rt,
323  dn,
324  up);
325 }
void allocateRestrictedBuffer(float **buf, const char *bufname)
Definition: HyPerLayer.cpp:325
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
static bool completed(Status &a)
Definition: Response.hpp:49
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override