8 #include "PresynapticPerspectiveStochasticDelivery.hpp" 9 #include "columns/HyPerCol.hpp" 16 PresynapticPerspectiveStochasticDelivery::PresynapticPerspectiveStochasticDelivery(
22 PresynapticPerspectiveStochasticDelivery::PresynapticPerspectiveStochasticDelivery() {}
24 PresynapticPerspectiveStochasticDelivery::~PresynapticPerspectiveStochasticDelivery() {
28 int PresynapticPerspectiveStochasticDelivery::initialize(
char const *name, HyPerCol *hc) {
29 return BaseObject::initialize(name, hc);
32 void PresynapticPerspectiveStochasticDelivery::setObjectType() {
33 mObjectType =
"PresynapticPerspectiveStochasticDelivery";
45 Response::Status PresynapticPerspectiveStochasticDelivery::communicateInitInfo(
46 std::shared_ptr<CommunicateInitInfoMessage const> message) {
47 auto status = HyPerDelivery::communicateInitInfo(message);
54 return Response::SUCCESS;
57 Response::Status PresynapticPerspectiveStochasticDelivery::allocateDataStructures() {
58 auto status = HyPerDelivery::allocateDataStructures();
64 return Response::SUCCESS;
67 void PresynapticPerspectiveStochasticDelivery::allocateThreadGSyn() {
69 int const numThreads = parent->getNumThreads();
71 mThreadGSyn.resize(numThreads);
74 for (
auto &th : mThreadGSyn) {
75 th.resize(mPostLayer->getNumNeurons());
80 void PresynapticPerspectiveStochasticDelivery::allocateRandState() {
81 mRandState =
new Random(mPreLayer->getLayerLoc(),
true );
86 if (getChannelCode() == CHANNEL_NOUPDATE) {
89 float *postChannel = mPostLayer->getChannel(getChannelCode());
90 pvAssert(postChannel);
92 PVLayerLoc const *preLoc = mPreLayer->getLayerLoc();
93 PVLayerLoc const *postLoc = mPostLayer->getLayerLoc();
94 Weights *weights = mWeightsPair->getPreWeights();
96 int const nxPreExtended = preLoc->nx + preLoc->halo.rt + preLoc->halo.rt;
97 int const nyPreExtended = preLoc->ny + preLoc->halo.dn + preLoc->halo.up;
98 int const numPreExtended = nxPreExtended * nyPreExtended * preLoc->nf;
100 int const numPostRestricted = postLoc->nx * postLoc->ny * postLoc->nf;
102 int nbatch = preLoc->nbatch;
103 pvAssert(nbatch == postLoc->nbatch);
105 const int sy = postLoc->nx * postLoc->nf;
106 const int syw = weights->
getGeometry()->getPatchStrideY();
108 bool const preLayerIsSparse = mPreLayer->getSparseFlag();
111 for (
int arbor = 0; arbor < numAxonalArbors; arbor++) {
112 int delay = mArborList->getDelay(arbor);
115 for (
int b = 0; b < nbatch; b++) {
116 size_t batchOffset = b * numPreExtended;
117 float *activityBatch = activityCube.data + batchOffset;
118 float *gSynPatchHeadBatch = postChannel + b * numPostRestricted;
120 if (preLayerIsSparse) {
126 preLayerIsSparse ? activityCube.numActive[b] : mPreLayer->getNumExtended();
128 #ifdef PV_USE_OPENMP_THREADS 130 if (!mThreadGSyn.empty()) {
131 #pragma omp parallel for schedule(static) 132 for (
int ti = 0; ti < parent->getNumThreads(); ++ti) {
133 for (
int ni = 0; ni < numPostRestricted; ++ni) {
134 mThreadGSyn[ti][ni] = 0.0;
140 std::size_t
const *gSynPatchStart = weights->
getGeometry()->getGSynPatchStart().data();
141 if (!preLayerIsSparse) {
143 #ifdef PV_USE_OPENMP_THREADS 144 #pragma omp parallel for schedule(guided) 146 for (
int idx = 0; idx < numNeurons; idx++) {
152 if (y >= patch->ny) {
157 float a = activityBatch[kPreExt];
161 a *= mDeltaTimeFactor;
164 float *gSynPatchHead = gSynPatchHeadBatch;
166 #ifdef PV_USE_OPENMP_THREADS 167 if (!mThreadGSyn.empty()) {
168 gSynPatchHead = mThreadGSyn[omp_get_thread_num()].data();
170 #endif // PV_USE_OPENMP_THREADS 172 float *postPatchStart = &gSynPatchHead[gSynPatchStart[kPreExt]];
176 float const *weightDataStart = &weightDataHead[patch->offset];
177 taus_uint4 *rng = mRandState->getRNG(kPreExt);
178 long along = (long)((
double)a * cl_random_max());
180 float *v = postPatchStart + y * sy;
181 float const *weightValues = weightDataStart + y * syw;
182 for (
int k = 0; k < nk; k++) {
183 *rng = cl_random_get(*rng);
184 v[k] += (rng->s0 < along) * weightValues[k];
191 for (
int y = 0; y < nyp; y++) {
192 #ifdef PV_USE_OPENMP_THREADS 193 #pragma omp parallel for schedule(guided) 195 for (
int idx = 0; idx < numNeurons; idx++) {
196 int kPreExt = activeIndicesBatch[idx].index;
201 if (y >= patch->ny) {
206 float a = activeIndicesBatch[idx].value;
210 a *= mDeltaTimeFactor;
213 float *gSynPatchHead = gSynPatchHeadBatch;
215 #ifdef PV_USE_OPENMP_THREADS 216 if (!mThreadGSyn.empty()) {
217 gSynPatchHead = mThreadGSyn[omp_get_thread_num()].data();
219 #endif // PV_USE_OPENMP_THREADS 221 float *postPatchStart = &gSynPatchHead[gSynPatchStart[kPreExt]];
225 float const *weightDataStart = &weightDataHead[patch->offset];
226 taus_uint4 *rng = mRandState->getRNG(kPreExt);
227 long along = (long)((
double)a * cl_random_max());
229 float *v = postPatchStart + y * sy;
230 float const *weightValues = weightDataStart + y * syw;
231 for (
int k = 0; k < nk; k++) {
232 *rng = cl_random_get(*rng);
233 v[k] += (rng->s0 < along) * weightValues[k];
238 #ifdef PV_USE_OPENMP_THREADS 241 if (!mThreadGSyn.empty()) {
242 float *gSynPatchHead = gSynPatchHeadBatch;
243 int numNeurons = mPostLayer->getNumNeurons();
244 for (
int ti = 0; ti < parent->getNumThreads(); ti++) {
245 float *onethread = mThreadGSyn[ti].data();
247 #pragma omp parallel for 248 for (
int ni = 0; ni < numNeurons; ni++) {
249 gSynPatchHead[ni] += onethread[ni];
253 #endif // PV_USE_OPENMP_THREADS 258 mPostLayer->setUpdatedDeviceGSynFlag(
true);
259 #endif // PV_USE_CUDA 262 void PresynapticPerspectiveStochasticDelivery::deliverUnitInput(
float *recvBuffer) {
263 PVLayerLoc const *preLoc = mPreLayer->getLayerLoc();
264 PVLayerLoc const *postLoc = mPostLayer->getLayerLoc();
265 Weights *weights = mWeightsPair->getPreWeights();
267 int const numPostRestricted = postLoc->nx * postLoc->ny * postLoc->nf;
269 int nbatch = postLoc->nbatch;
271 const int sy = postLoc->nx * postLoc->nf;
272 const int syw = weights->
getGeometry()->getPatchStrideY();
275 for (
int arbor = 0; arbor < numAxonalArbors; arbor++) {
276 int delay = mArborList->getDelay(arbor);
279 for (
int b = 0; b < nbatch; b++) {
280 float *recvBatch = recvBuffer + b * numPostRestricted;
281 int numNeurons = mPreLayer->getNumExtended();
283 #ifdef PV_USE_OPENMP_THREADS 285 if (!mThreadGSyn.empty()) {
286 #pragma omp parallel for schedule(static) 287 for (
int ti = 0; ti < parent->getNumThreads(); ++ti) {
288 for (
int ni = 0; ni < numPostRestricted; ++ni) {
289 mThreadGSyn[ti][ni] = 0.0;
295 std::size_t
const *gSynPatchStart = weights->
getGeometry()->getGSynPatchStart().data();
297 #ifdef PV_USE_OPENMP_THREADS 298 #pragma omp parallel for schedule(guided) 300 for (
int idx = 0; idx < numNeurons; idx++) {
306 if (y >= patch->ny) {
311 float a = mDeltaTimeFactor;
314 float *recvPatchHead = recvBatch;
316 #ifdef PV_USE_OPENMP_THREADS 317 if (!mThreadGSyn.empty()) {
318 recvPatchHead = mThreadGSyn[omp_get_thread_num()].data();
320 #endif // PV_USE_OPENMP_THREADS 322 float *postPatchStart = &recvPatchHead[gSynPatchStart[kPreExt]];
326 float const *weightDataStart = &weightDataHead[patch->offset];
327 taus_uint4 *rng = mRandState->getRNG(kPreExt);
328 long along = (long)cl_random_max();
330 float *v = postPatchStart + y * sy;
331 float const *weightValues = weightDataStart + y * syw;
332 for (
int k = 0; k < nk; k++) {
333 *rng = cl_random_get(*rng);
334 v[k] += (rng->s0 < along) * weightValues[k];
338 #ifdef PV_USE_OPENMP_THREADS 341 if (!mThreadGSyn.empty()) {
342 float *recvPatchHead = recvBatch;
343 int numNeurons = mPostLayer->getNumNeurons();
344 for (
int ti = 0; ti < parent->getNumThreads(); ti++) {
345 float *onethread = mThreadGSyn[ti].data();
347 #pragma omp parallel for 348 for (
int ni = 0; ni < numNeurons; ni++) {
349 recvPatchHead[ni] += onethread[ni];
353 #endif // PV_USE_OPENMP_THREADS
PVLayerCube createCube(int delay=0)
static bool completed(Status &a)
Patch const & getPatch(int patchIndex) const
int getPatchSizeY() const
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
std::shared_ptr< PatchGeometry > getGeometry() const
int getNumAxonalArbors() const
float * getDataFromPatchIndex(int arbor, int patchIndex)
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
virtual void deliver() override
virtual void ioParam_receiveGpu(enum ParamsIOFlag ioFlag) override
receiveGpu: PresynapticPerspectiveStochasticDelivery always sets receiveGpu to false. The receiveGpu=true case is handled by the PresynapticPerspectiveGPUDelivery class.
int getPatchSizeF() const
bool getInitInfoCommunicatedFlag() const