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