8 #include "PresynapticPerspectiveConvolveDelivery.hpp" 9 #include "columns/HyPerCol.hpp" 13 PresynapticPerspectiveConvolveDelivery::PresynapticPerspectiveConvolveDelivery(
19 PresynapticPerspectiveConvolveDelivery::PresynapticPerspectiveConvolveDelivery() {}
21 PresynapticPerspectiveConvolveDelivery::~PresynapticPerspectiveConvolveDelivery() {}
23 int PresynapticPerspectiveConvolveDelivery::initialize(
char const *name, HyPerCol *hc) {
24 return BaseObject::initialize(name, hc);
27 void PresynapticPerspectiveConvolveDelivery::setObjectType() {
28 mObjectType =
"PresynapticPerspectiveConvolveDelivery";
40 Response::Status PresynapticPerspectiveConvolveDelivery::communicateInitInfo(
41 std::shared_ptr<CommunicateInitInfoMessage const> message) {
42 auto status = HyPerDelivery::communicateInitInfo(message);
49 return Response::SUCCESS;
52 Response::Status PresynapticPerspectiveConvolveDelivery::allocateDataStructures() {
53 auto status = HyPerDelivery::allocateDataStructures();
58 return Response::SUCCESS;
61 void PresynapticPerspectiveConvolveDelivery::allocateThreadGSyn() {
63 int const numThreads = parent->getNumThreads();
65 mThreadGSyn.resize(numThreads);
68 for (
auto &th : mThreadGSyn) {
69 th.resize(mPostLayer->getNumNeurons());
76 if (getChannelCode() == CHANNEL_NOUPDATE) {
79 float *postChannel = mPostLayer->getChannel(getChannelCode());
80 pvAssert(postChannel);
82 PVLayerLoc const *preLoc = mPreLayer->getLayerLoc();
83 PVLayerLoc const *postLoc = mPostLayer->getLayerLoc();
84 Weights *weights = mWeightsPair->getPreWeights();
86 int const nxPreExtended = preLoc->nx + preLoc->halo.rt + preLoc->halo.rt;
87 int const nyPreExtended = preLoc->ny + preLoc->halo.dn + preLoc->halo.up;
88 int const numPreExtended = nxPreExtended * nyPreExtended * preLoc->nf;
90 int const numPostRestricted = postLoc->nx * postLoc->ny * postLoc->nf;
92 int nbatch = preLoc->nbatch;
93 pvAssert(nbatch == postLoc->nbatch);
95 const int sy = postLoc->nx * postLoc->nf;
96 const int syw = weights->
getGeometry()->getPatchStrideY();
98 bool const preLayerIsSparse = mPreLayer->getSparseFlag();
101 for (
int arbor = 0; arbor < numAxonalArbors; arbor++) {
102 int delay = mArborList->getDelay(arbor);
105 for (
int b = 0; b < nbatch; b++) {
106 size_t batchOffset = b * numPreExtended;
107 float *activityBatch = activityCube.data + batchOffset;
108 float *gSynPatchHeadBatch = postChannel + b * numPostRestricted;
110 if (preLayerIsSparse) {
116 preLayerIsSparse ? activityCube.numActive[b] : mPreLayer->getNumExtended();
118 #ifdef PV_USE_OPENMP_THREADS 120 if (!mThreadGSyn.empty()) {
121 #pragma omp parallel for schedule(static) 122 for (
int ti = 0; ti < parent->getNumThreads(); ++ti) {
123 for (
int ni = 0; ni < numPostRestricted; ++ni) {
124 mThreadGSyn[ti][ni] = 0.0;
130 std::size_t
const *gSynPatchStart = weights->
getGeometry()->getGSynPatchStart().data();
131 if (!preLayerIsSparse) {
133 #ifdef PV_USE_OPENMP_THREADS 134 #pragma omp parallel for schedule(guided) 136 for (
int idx = 0; idx < numNeurons; idx++) {
142 if (y >= patch->ny) {
147 float a = activityBatch[kPreExt];
151 a *= mDeltaTimeFactor;
154 float *gSynPatchHead = gSynPatchHeadBatch;
156 #ifdef PV_USE_OPENMP_THREADS 157 if (!mThreadGSyn.empty()) {
158 gSynPatchHead = mThreadGSyn[omp_get_thread_num()].data();
160 #endif // PV_USE_OPENMP_THREADS 162 float *postPatchStart = &gSynPatchHead[gSynPatchStart[kPreExt]];
166 float const *weightDataStart = &weightDataHead[patch->offset];
168 float *v = postPatchStart + y * sy;
169 float const *weightValues = weightDataStart + y * syw;
170 for (
int k = 0; k < nk; k++) {
171 v[k] += a * weightValues[k];
178 for (
int y = 0; y < nyp; y++) {
179 #ifdef PV_USE_OPENMP_THREADS 180 #pragma omp parallel for schedule(guided) 182 for (
int idx = 0; idx < numNeurons; idx++) {
183 int kPreExt = activeIndicesBatch[idx].index;
188 if (y >= patch->ny) {
193 float a = activeIndicesBatch[idx].value;
197 a *= mDeltaTimeFactor;
200 float *gSynPatchHead = gSynPatchHeadBatch;
202 #ifdef PV_USE_OPENMP_THREADS 203 if (!mThreadGSyn.empty()) {
204 gSynPatchHead = mThreadGSyn[omp_get_thread_num()].data();
206 #endif // PV_USE_OPENMP_THREADS 208 float *postPatchStart = &gSynPatchHead[gSynPatchStart[kPreExt]];
212 float const *weightDataStart = &weightDataHead[patch->offset];
214 float *v = postPatchStart + y * sy;
215 float const *weightValues = weightDataStart + y * syw;
216 for (
int k = 0; k < nk; k++) {
217 v[k] += a * weightValues[k];
222 #ifdef PV_USE_OPENMP_THREADS 225 if (!mThreadGSyn.empty()) {
226 float *gSynPatchHead = gSynPatchHeadBatch;
227 int numNeurons = mPostLayer->getNumNeurons();
228 for (
int ti = 0; ti < parent->getNumThreads(); ti++) {
229 float *onethread = mThreadGSyn[ti].data();
231 #pragma omp parallel for 232 for (
int ni = 0; ni < numNeurons; ni++) {
233 gSynPatchHead[ni] += onethread[ni];
237 #endif // PV_USE_OPENMP_THREADS 242 mPostLayer->setUpdatedDeviceGSynFlag(
true);
243 #endif // PV_USE_CUDA 246 void PresynapticPerspectiveConvolveDelivery::deliverUnitInput(
float *recvBuffer) {
247 PVLayerLoc const *postLoc = mPostLayer->getLayerLoc();
248 Weights *weights = mWeightsPair->getPreWeights();
250 int const numPostRestricted = postLoc->nx * postLoc->ny * postLoc->nf;
252 int nbatch = postLoc->nbatch;
254 const int sy = postLoc->nx * postLoc->nf;
255 const int syw = weights->
getGeometry()->getPatchStrideY();
258 for (
int arbor = 0; arbor < numAxonalArbors; arbor++) {
259 for (
int b = 0; b < nbatch; b++) {
260 float *recvBatch = recvBuffer + b * numPostRestricted;
263 int numNeurons = mPreLayer->getNumExtended();
265 #ifdef PV_USE_OPENMP_THREADS 267 if (!mThreadGSyn.empty()) {
268 #pragma omp parallel for schedule(static) 269 for (
int ti = 0; ti < parent->getNumThreads(); ++ti) {
270 for (
int ni = 0; ni < numPostRestricted; ++ni) {
271 mThreadGSyn[ti][ni] = 0.0;
277 std::size_t
const *gSynPatchStart = weights->
getGeometry()->getGSynPatchStart().data();
279 #ifdef PV_USE_OPENMP_THREADS 280 #pragma omp parallel for schedule(guided) 282 for (
int idx = 0; idx < numNeurons; idx++) {
288 if (y >= patch->ny) {
293 float *recvPatchHead = recvBatch;
295 #ifdef PV_USE_OPENMP_THREADS 296 if (!mThreadGSyn.empty()) {
297 recvPatchHead = mThreadGSyn[omp_get_thread_num()].data();
299 #endif // PV_USE_OPENMP_THREADS 301 float *postPatchStart = &recvPatchHead[gSynPatchStart[kPreExt]];
305 float const *weightDataStart = &weightDataHead[patch->offset];
307 float *v = postPatchStart + y * sy;
308 float const *weightValues = weightDataStart + y * syw;
309 for (
int k = 0; k < nk; k++) {
310 v[k] += mDeltaTimeFactor * weightValues[k];
314 #ifdef PV_USE_OPENMP_THREADS 317 if (!mThreadGSyn.empty()) {
318 float *recvPatchHead = recvBatch;
319 int numNeurons = mPostLayer->getNumNeurons();
320 for (
int ti = 0; ti < parent->getNumThreads(); ti++) {
321 float *onethread = mThreadGSyn[ti].data();
323 #pragma omp parallel for 324 for (
int ni = 0; ni < numNeurons; ni++) {
325 recvPatchHead[ni] += onethread[ni];
329 #endif // PV_USE_OPENMP_THREADS virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
PVLayerCube createCube(int delay=0)
static bool completed(Status &a)
Patch const & getPatch(int patchIndex) const
int getPatchSizeY() const
std::shared_ptr< PatchGeometry > getGeometry() const
int getNumAxonalArbors() const
float * getDataFromPatchIndex(int arbor, int patchIndex)
virtual void deliver() override
virtual void ioParam_receiveGpu(enum ParamsIOFlag ioFlag) override
receiveGpu: PresynapticPerspectiveConvolveDelivery always sets receiveGpu to false. The receiveGpu=true case is handled by the PresynapticPerspectiveGPUDelivery class.
virtual int ioParamsFillGroup(enum ParamsIOFlag ioFlag) override
int getPatchSizeF() const
bool getInitInfoCommunicatedFlag() const