int MomentumConn::updateWeights(int arborId){ if(timeBatchIdx != timeBatchPeriod - 1){ return PV_SUCCESS; } //Add momentum right before updateWeights for(int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++){ applyMomentum(arborId); } //Saved to prevweights assert(prev_dwDataStart); std::memcpy(*prev_dwDataStart, *get_dwDataStart(), sizeof(pvwdata_t) * numberOfAxonalArborLists() * nxp * nyp * nfp * getNumDataPatches()); // add dw to w for(int kArbor = 0; kArbor < this->numberOfAxonalArborLists(); kArbor++){ pvwdata_t * w_data_start = get_wDataStart(kArbor); for( long int k=0; k<patchStartIndex(getNumDataPatches()); k++ ) { w_data_start[k] += get_dwDataStart(kArbor)[k]; } } return PV_BREAK; }
int MomentumConn::allocateDataStructures(){ HyPerConn::allocateDataStructures(); if (!plasticityFlag) return PV_SUCCESS; int sx = nfp; int sy = sx * nxp; int sp = sy * nyp; int nPatches = getNumDataPatches(); const int numAxons = numberOfAxonalArborLists(); //Allocate dw buffer for previous dw prev_dwDataStart = (pvwdata_t **) calloc(numAxons, sizeof(pvwdata_t *)); if( prev_dwDataStart == NULL ) { createArborsOutOfMemory(); assert(false); } prev_dwDataStart[0] = (pvwdata_t*) calloc(numAxons * nxp * nyp * nfp * nPatches, sizeof(pvwdata_t)); assert(prev_dwDataStart[0] != NULL); for (int arborId = 0; arborId < numAxons; arborId++) { prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId); assert(prev_dwDataStart[arborId] != NULL); } // loop over arbors assert(clones.size() == 0); return PV_SUCCESS; }
int PoolingConn::constructWeights() { int sx = nfp; int sy = sx * nxp; int sp = sy * nyp; int nPatches = getNumDataPatches(); int status = PV_SUCCESS; assert(!parent->parameters()->presentAndNotBeenRead(name, "shrinkPatches")); // createArbors() uses the value of shrinkPatches. It should have already been read in ioParamsFillGroup. //allocate the arbor arrays: createArbors(); setPatchStrides(); for (int arborId=0; arborId<numAxonalArborLists; arborId++) { PVPatch *** wPatches = get_wPatches(); status = createWeights(wPatches, arborId); assert(wPatches[arborId] != NULL); if (shrinkPatches_flag || arborId == 0) { status |= adjustAxonalArbors(arborId); } } // arborId //call to initializeWeights moved to BaseConnection::initializeState() status |= initPlasticityPatches(); assert(status == 0); if (shrinkPatches_flag) { for (int arborId=0; arborId<numAxonalArborLists; arborId++) { shrinkPatches(arborId); } } return status; }
int MomentumConn::checkpointRead(const char * cpDir, double * timeptr) { HyPerConn::checkpointRead(cpDir, timeptr); if (!plasticityFlag) return PV_SUCCESS; clearWeights(prev_dwDataStart, getNumDataPatches(), nxp, nyp, nfp); char * path = parent->pathInCheckpoint(cpDir, getName(), "_prev_dW.pvp"); PVPatch *** patches_arg = sharedWeights ? NULL : get_wPatches(); double filetime=0.0; int status = PV::readWeights(patches_arg, prev_dwDataStart, numberOfAxonalArborLists(), getNumDataPatches(), nxp, nyp, nfp, path, parent->icCommunicator(), &filetime, pre->getLayerLoc()); if (parent->columnId()==0 && timeptr && *timeptr != filetime) { fprintf(stderr, "Warning: \"%s\" checkpoint has timestamp %g instead of the expected value %g.\n", path, filetime, *timeptr); } free(path); return status; }
int GradientCheckConn::allocateDataStructures() { int status = PV::HyPerConn::allocateDataStructures(); //Check num weights against num timesteps int numDataPatches = getNumDataPatches(); int numWeights = nxp * nyp * nfp; int numArbors = numAxonalArborLists; if(parent->getFinalStep() - parent->getInitialStep() > numDataPatches * numWeights * numArbors + 2){ std::cout << "Maximum number of steps for GradientCheckConn is " << numDataPatches * numWeights * numArbors + 2 << "\n"; exit(-1); } return status; }
//TODO checkpointing not working with batching, must write checkpoint exactly at period int MomentumConn::checkpointWrite(const char * cpDir) { HyPerConn::checkpointWrite(cpDir); if (!plasticityFlag) return PV_SUCCESS; char filename[PV_PATH_MAX]; int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_prev_dW.pvp", cpDir, name); if(chars_needed >= PV_PATH_MAX) { if ( parent->icCommunicator()->commRank()==0 ) { fprintf(stderr, "HyPerConn::checkpointFilename error: path \"%s/%s_W.pvp\" is too long.\n", cpDir, name); } abort(); } PVPatch *** patches_arg = sharedWeights ? NULL : get_wPatches(); int status = writeWeights(patches_arg, prev_dwDataStart, getNumDataPatches(), filename, parent->simulationTime(), writeCompressedCheckpoints, /*last*/true); assert(status==PV_SUCCESS); return PV_SUCCESS; }
int VaryingHyPerConn::updateWeights(int axonId) { int syPatch = yPatchStride(); for( int kPatch = 0; kPatch < getNumDataPatches(); kPatch++) { PVPatch * W = getWeights(kPatch, axonId); int nkPatch = fPatchSize() * W->nx; pvwdata_t * Wdata = get_wData(axonId, kPatch); // W->data; pvdata_t * dWdata = get_dwData(axonId, kPatch); for(int kyPatch = 0; kyPatch < W->ny; kyPatch++) { for(int kPatch = 0; kPatch < nkPatch; kPatch++) { Wdata[kPatch] += dWdata[kPatch]; } dWdata += syPatch; } } return PV_SUCCESS; }
int LCALIFLateralKernelConn::checkpointWrite(const char * cpDir) { int status = HyPerConn::checkpointWrite(cpDir); char filename[PV_PATH_MAX]; int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name); if (chars_needed >= PV_PATH_MAX) { fprintf(stderr, "LCALIFLateralKernelConn::checkpointWrite error. Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name); abort(); } int status2 = HyPerLayer::writeBufferFile(filename, parent->icCommunicator(), parent->simulationTime(), &integratedSpikeCount, 1/*numbands*/, false/*extended*/, pre->getLayerLoc()); if (status2!=PV_SUCCESS) status = status2; chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_dW.pvp", cpDir, name); assert(chars_needed < PV_PATH_MAX); status2 = HyPerConn::writeWeights(NULL, get_dwDataStart(), getNumDataPatches(), filename, parent->simulationTime(), writeCompressedCheckpoints, true); if (status2!=PV_SUCCESS) status = status2; return status; }
int LCAConn::update_dW(int axonId) { // compute dW but don't add them to the weights yet. // That takes place in reduceKernels, so that the output is // independent of the number of processors. int nExt = preSynapticLayer()->getNumExtended(); int numKernelIndices = getNumDataPatches(); const pvdata_t * preactbuf = preSynapticLayer()->getLayerData(getDelay(axonId)); const pvdata_t * postactbuf = postSynapticLayer()->getLayerData(getDelay(axonId)); int sya = (post->getLayerLoc()->nf * (post->getLayerLoc()->nx + 2*post->getLayerLoc()->nb)); for(int kExt=0; kExt<nExt;kExt++) { PVPatch * weights = getWeights(kExt,axonId); size_t offset = getAPostOffset(kExt, axonId); pvdata_t preact = preactbuf[kExt]; int ny = weights->ny; int nk = weights->nx * nfp; const pvdata_t * postactRef = &postactbuf[offset]; pvdata_t * dwdata = get_dwData(axonId, kExt); int lineoffsetw = 0; int lineoffseta = 0; for( int y=0; y<ny; y++ ) { for( int k=0; k<nk; k++ ) { dwdata[lineoffsetw + k] += updateRule_dW(preact, postactRef[lineoffseta+k],lineoffseta+k); } lineoffsetw += syp; lineoffseta += sya; } } // Divide by (numNeurons/numKernels) int divisor = pre->getNumNeurons()/numKernelIndices; assert( divisor*numKernelIndices == pre->getNumNeurons() ); for( int kernelindex=0; kernelindex<numKernelIndices; kernelindex++ ) { int numpatchitems = nxp*nyp*nfp; pvdata_t * dwpatchdata = get_dwDataHead(axonId,kernelindex); for( int n=0; n<numpatchitems; n++ ) { dwpatchdata[n] /= divisor; } } lastUpdateTime = parent->simulationTime(); return PV_SUCCESS; }
int VaryingHyPerConn::allocateDataStructures() { HyPerConn::allocateDataStructures(); // initialize all dW's to one. int syPatch = yPatchStride(); for(int kAxon = 0; kAxon < numberOfAxonalArborLists(); kAxon++){ for(int kPatch = 0; kPatch < getNumDataPatches(); kPatch++){ PVPatch * W = getWeights(kPatch, kAxon); int nkPatch = fPatchSize() * W->nx; float * dWdata = get_dwData(kAxon, kPatch); for(int kyPatch = 0; kyPatch < W->ny; kyPatch++){ for(int kPatch = 0; kPatch < nkPatch; kPatch++){ dWdata[kPatch] = 1.0f; } dWdata += syPatch; } } } return PV_SUCCESS; }
int LCALIFLateralKernelConn::updateWeights(int axonId) { if (plasticityFlag) { float normalizer = parent->getDeltaTime()/getInhibitionTimeConstant(); for (int kernel=0; kernel<getNumDataPatches(); kernel++) { pvwdata_t * dw_data = get_dwDataHead(axonId,kernel); pvwdata_t * w_data = get_wDataHead(axonId,kernel); for (int y=0; y<nyp; y++) { for (int x=0; x<nxp; x++) { for (int f=0; f<nfp; f++) { int idx = sxp*x + syp*y + sfp*f; pvdata_t dw = dw_data[idx] * normalizer; pvwdata_t w = w_data[idx] + (weightUpdatePeriod/parent->getDeltaTime())*dw; if (w<0) w=0; w_data[idx] = w; } } } } } return PV_SUCCESS; }
int MomentumConn::applyMomentum(int arbor_ID){ int nExt = preSynapticLayer()->getNumExtended(); const PVLayerLoc * loc = preSynapticLayer()->getLayerLoc(); if(sharedWeights){ int numKernels = getNumDataPatches(); //Shared weights done in parallel, parallel in numkernels #ifdef PV_USE_OPENMP_THREADS #pragma omp parallel for #endif for(int kernelIdx = 0; kernelIdx < numKernels; kernelIdx++){ pvwdata_t * dwdata_start = get_dwDataHead(arbor_ID, kernelIdx); pvwdata_t * prev_dw_start = get_prev_dwDataHead(arbor_ID, kernelIdx); pvwdata_t * wdata_start = get_wDataHead(arbor_ID, kernelIdx); if(!strcmp(momentumMethod, "simple")){ for(int k = 0; k < nxp*nyp*nfp; k++){ dwdata_start[k] += momentumTau * prev_dw_start[k] - momentumDecay*wdata_start[k]; } } else if(!strcmp(momentumMethod, "viscosity")){ for(int k = 0; k < nxp*nyp*nfp; k++){ //dwdata_start[k] = momentumTau * (prev_dw_start[k] + dwdata_start[k]) * (1 - exp(-1.0/ momentumTau)) - momentumDecay*wdata_start[k]; dwdata_start[k] = (prev_dw_start[k] * exp(-1.0/ momentumTau)) + dwdata_start[k] - momentumDecay*wdata_start[k]; } } else if(!strcmp(momentumMethod, "alex")){ for(int k = 0; k < nxp*nyp*nfp; k++){ //weight_inc[i] := momW * weight_inc[i-1] - wc * epsW * weights[i-1] + epsW * weight_grads[i] // weights[i] := weights[i-1] + weight_inc[i] dwdata_start[k] = momentumTau * prev_dw_start[k] - momentumDecay * getDWMax()* wdata_start[k] + dwdata_start[k]; } } } } else{ std::cout << "Warning: Momentum not implemented for non-shared weights, not implementing momentum\n"; } return PV_SUCCESS; }
int MomentumConn::allocateDataStructures(){ int status = HyPerConn::allocateDataStructures(); if (status==PV_POSTPONE) { return status; } if (!plasticityFlag) return status; int sx = nfp; int sy = sx * nxp; int sp = sy * nyp; int nPatches = getNumDataPatches(); const int numAxons = numberOfAxonalArborLists(); //Allocate dw buffer for previous dw prev_dwDataStart = (pvwdata_t **) pvCalloc(numAxons, sizeof(pvwdata_t *)); prev_dwDataStart[0] = (pvwdata_t*) pvCalloc(numAxons * nxp * nyp * nfp * nPatches, sizeof(pvwdata_t)); for (int arborId = 0; arborId < numAxons; arborId++) { prev_dwDataStart[arborId] = (prev_dwDataStart[0] + sp * nPatches * arborId); assert(prev_dwDataStart[arborId] != NULL); } // loop over arbors //assert(clones.size() == 0); return PV_SUCCESS; }
int CopyConn::copy(int arborId) { size_t arborsize = (size_t) (xPatchSize() * yPatchSize() * fPatchSize() * getNumDataPatches()) * sizeof(pvwdata_t); memcpy(get_wDataStart(arborId), originalConn->get_wDataStart(arborId), arborsize); return PV_SUCCESS; }
//Connections update first int GradientCheckConn::updateState(double time, double dt){ int status = PV_SUCCESS; int weightIdx = parent->getCurrentStep() - parent->getInitialStep() - 2; std::cout << "weightIdx " << weightIdx << "\n"; int numPatch = nxp * nyp * nfp; int numData = getNumDataPatches(); int arborIdx = weightIdx / (numPatch * numData); int dataIdx = (weightIdx / numPatch) % numData; int patchIdx = weightIdx % numPatch; if(firstRun){ initialize_dW(0); firstRun = false; return PV_SUCCESS; } //Grab cost from previous timestep if(secondRun){ //First run does regular updateState to calculate dw buffer for(int arborId=0;arborId<numberOfAxonalArborLists();arborId++) { status = calc_dW(); // Calculate changes in weights if (status==PV_BREAK) { break; } assert(status == PV_SUCCESS); } //for (int arborID = 0; arborID < numberOfAxonalArborLists(); arborID++) { // if(sharedWeights){ // status = reduceKernels(arborID); // combine partial changes in each column // if (status == PV_BREAK) { // break; // } // assert(status == PV_SUCCESS); // } //} //No update weights origCost = getCost(); secondRun = false; } //Does not update after first run //Check if we are in bounds for non-shared weights if(!sharedWeights){ PVPatch* weights = getWeights(dataIdx, arborIdx); //Calculate x and y of patchIdx and compare it to offset int xPatchIdx = kxPos(patchIdx, nxp, nyp, nfp); int yPatchIdx = kyPos(patchIdx, nxp, nyp, nfp); int xOffsetIdx = kxPos(weights->offset, nxp, nyp, nfp); int yOffsetIdx = kyPos(weights->offset, nxp, nyp, nfp); //If index is oob, skip if(xPatchIdx < xOffsetIdx || xPatchIdx >= xOffsetIdx + weights->nx || yPatchIdx < yOffsetIdx || yPatchIdx >= yOffsetIdx + weights->ny){ return PV_SUCCESS; } } //Calculate difference in numerical method and backprop method if(prevIdx != -1){ currCost = getCost(); //Check for accuracy float numGradient = (currCost - origCost)/epsilon; float backpropGradient = get_dwDataStart()[0][prevIdx] / dWMax; std::cout << "Numerical gradient: " << numGradient << " Backprop gradient: " << backpropGradient << "\n"; //if(fabs(numGradient + backpropGradient) >= .1){ // std::cout << "Numerical gradient: " << numGradient << " Backprop gradient: " << backpropGradient << "\n"; // exit(-1); //} } //Restore weight if(prevIdx != -1){ std::cout << "Restoring weight " << prevIdx << " to " << prevWeightVal << "\n"; get_wDataStart()[0][prevIdx] = prevWeightVal; } //Set next weight if not the end if(weightIdx < numberOfAxonalArborLists() * numData * numPatch){ prevWeightVal = get_wDataStart()[0][weightIdx]; prevIdx = weightIdx; get_wDataStart()[0][weightIdx] += epsilon; std::cout << "Setting weight " << weightIdx << " to " << prevWeightVal + epsilon << "\n"; } else{ std::cout << "END\n"; } return status; }
int LCALIFLateralKernelConn::allocateDataStructures() { int status = HyPerConn::allocateDataStructures(); // Neurons don't inhibit themselves, only their neighbors; set self-interaction weights to mmzero. assert(nxp % 2 == 1 && nyp % 2 == 1 && getNumDataPatches()==nfp); for (int k=0; k<getNumDataPatches(); k++) { int n = kIndex((nxp-1)/2, (nyp-1)/2, k, nxp, nyp, nfp); get_wDataHead(0, k)[n] = 0.0f; } integratedSpikeCountCube = pvcube_new(pre->getLayerLoc(), pre->getNumExtended()); integratedSpikeCount = integratedSpikeCountCube->data; for (int k=0; k<pre->getNumExtended(); k++) { integratedSpikeCount[k] = integrationTimeConstant*getTargetRateKHz(); // Spike counts initialized to equilibrium value } mpi_datatype = Communicator::newDatatypes(pre->getLayerLoc()); if (mpi_datatype==NULL) { fprintf(stderr, "LCALIFLateralKernelConn \"%s\" error creating mpi_datatype\n", name); abort(); } // Compute the number of times each patch contributes to dw, for proper averaging. int num_arbors = numberOfAxonalArborLists(); interiorCounts = (float **) calloc(num_arbors, sizeof(float *)); if (interiorCounts==NULL) { fprintf(stderr, "LCALIFLateralKernelConn::initialize \"%s\" error: unable to allocate memory for interiorCounts pointer\n", name); } interiorCounts[0] = (float *) calloc(getNumDataPatches()*nxp*nyp*nfp, sizeof(float)); if (interiorCounts[0]==NULL) { fprintf(stderr, "LCALIFLateralKernelConn::initialize \"%s\" error: unable to allocate memory for interiorCounts\n", name); } for (int arbor=1; arbor<num_arbors; arbor++) { interiorCounts[arbor] = interiorCounts[0]+arbor*getNumDataPatches()*nxp*nyp*nfp; } const PVLayerLoc * preloc = pre->getLayerLoc(); int nxpre = preloc->nx; int nypre = preloc->ny; int nfpre = preloc->nf; int nExt = pre->getNumExtended(); int sya = getPostExtStrides()->sy; int nxglob = preloc->nxGlobal; int nyglob = preloc->nyGlobal; int kx0 = preloc->kx0; int ky0 = preloc->ky0; for (int arbor=0; arbor<numberOfAxonalArborLists(); arbor++) { for(int kExt=0; kExt<nExt;kExt++) { int xglob = kxPos(kExt, nxpre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + kx0 - preloc->halo.lt; int yglob = kyPos(kExt, nypre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + ky0 - preloc->halo.up; if (xglob < 0 || xglob >= nxglob || yglob < 0 || yglob >= nyglob) { continue; } PVPatch * weights = getWeights(kExt,arbor); int offset = (int) getAPostOffset(kExt, arbor); int ny = weights->ny; int nk = weights->nx * nfp; int interiorCountOffset = get_wData(arbor, kExt)-get_wDataStart(arbor); int lineoffsetw = 0; int lineoffseta = 0; for( int y=0; y<ny; y++ ) { for( int k=0; k<nk; k++ ) { int postactindex = offset+lineoffseta+k; if (postactindex != kExt) { // Neurons don't inhibit themselves interiorCounts[arbor][interiorCountOffset + lineoffsetw + k]++; } } lineoffsetw += syp; lineoffseta += sya; } } } int bufsize = numberOfAxonalArborLists() * getNumDataPatches() * nxp * nyp * nfp; // TODO-CER-2014.3.26 - Ensure that reduction is done when not using MPI #ifdef PV_USE_MPI MPI_Allreduce(MPI_IN_PLACE, interiorCounts[0], bufsize, MPI_FLOAT, MPI_SUM, parent->icCommunicator()->communicator()); #endif return status; }
int LCALIFLateralKernelConn::update_dW(int axonId) { if (parent->simulationTime() < dWUpdateTime) { return PV_SUCCESS; } dWUpdateTime += dWUpdatePeriod; int nExt = preSynapticLayer()->getNumExtended(); int numKernelIndices = getNumDataPatches(); updateIntegratedSpikeCount(); float target_rate_sq = getTargetRateKHz()*getTargetRateKHz(); const pvdata_t * preactbuf = integratedSpikeCount; const pvdata_t * postactbuf = integratedSpikeCount; int sya = (post->getLayerLoc()->nf * (post->getLayerLoc()->nx + post->getLayerLoc()->halo.lt + post->getLayerLoc()->halo.rt)); const PVLayerLoc * preloc = pre->getLayerLoc(); int nxpre = preloc->nx; int nypre = preloc->ny; int nfpre = preloc->nf; int nxglob = preloc->nxGlobal; int nyglob = preloc->nyGlobal; int kx0 = preloc->kx0; int ky0 = preloc->ky0; for(int kExt=0; kExt<nExt;kExt++) { int xglob = kxPos(kExt, nxpre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + kx0 - preloc->halo.lt; int yglob = kyPos(kExt, nxpre + preloc->halo.lt + preloc->halo.rt, nypre + preloc->halo.dn + preloc->halo.up, nfpre) + ky0 - preloc->halo.dn; if (xglob < 0 || xglob >= nxglob || yglob < 0 || yglob >= nyglob) { continue; } PVPatch * weights = getWeights(kExt,axonId); size_t offset = getAPostOffset(kExt, axonId); pvdata_t preactrate = preactbuf[kExt]/integrationTimeConstant; int ny = weights->ny; int nk = weights->nx * nfp; pvwdata_t * dwdata = get_dwData(axonId, kExt); int lineoffsetw = 0; int lineoffseta = 0; for( int y=0; y<ny; y++ ) { for( int k=0; k<nk; k++ ) { int postactindex = offset+lineoffseta+k; if (postactindex != kExt) { // Neurons don't inhibit themselves pvdata_t postactrate = postactbuf[postactindex]/integrationTimeConstant; pvdata_t dw = preactrate*postactrate-target_rate_sq; dwdata[lineoffsetw + k] += dw; } } lineoffsetw += syp; lineoffseta += sya; } } // Divide each dw by the number of correlations that contributed to that dw (divisorptr was summed over all MPI processes in initialization). // Also divide by target_rate_sq to normalize to a dimensionless quantity. // The nonlinear filter and the multiplication by dt/tauINH takes place in updateWeights, because the filter has to be applied after reduceKernels // and the multiplication by dt/tauINH needs to take place after the filter. int patch_size = nxp*nyp*nfp; for( int kernelindex=0; kernelindex<numKernelIndices; kernelindex++ ) { pvwdata_t * dwpatchdata = get_dwDataHead(axonId,kernelindex); float * divisorptr = &interiorCounts[axonId][kernelindex*patch_size]; for( int n=0; n<patch_size; n++ ) { assert(divisorptr[n]>0 || dwpatchdata[n]==0); if (divisorptr[n]>0) dwpatchdata[n] /= target_rate_sq * divisorptr[n]; } } lastUpdateTime = parent->simulationTime(); return PV_SUCCESS; }
int MapReduceKernelConn::reduceKernels(const int arborID) { int status = HyPerConn::reduceKernels(arborID); int rootproc = 0; InterColComm *icComm = parent->icCommunicator(); const int numPatches = getNumDataPatches(); const size_t patchSize = nxp * nyp * nfp * sizeof(pvdata_t); const size_t localSize = numPatches * patchSize; const size_t arborSize = localSize * this->numberOfAxonalArborLists(); if (icComm->commRank() == rootproc) { // write dW for this instantiation of PetaVision to disk status = HyPerConn::writeWeights(NULL, this->get_dwDataStart(), getNumDataPatches(), dWeightsList[dWeightFileIndex], parent->simulationTime(), /*writeCompressedWeights*/false, /*last*/ false); if (status != PV_SUCCESS) { fprintf(stderr, "MapReduceKernelConn::reduceKernels::HyPerConn::writeWeights: problem writing to file %s, " "SHUTTING DOWN\n", dWeightsList[dWeightFileIndex]); exit(EXIT_FAILURE); } // status // use dWeightsList to read in the weights written by other PetaVision instantiations double dW_time; double simulation_time = parent->simulationTime(); int filetype, datatype; int numParams = NUM_BIN_PARAMS + NUM_WGT_EXTRA_PARAMS; int params[NUM_BIN_PARAMS + NUM_WGT_EXTRA_PARAMS]; const PVLayerLoc *preLoc = this->preSynapticLayer()->getLayerLoc(); int file_count = 0; for (file_count = 0; file_count < num_dWeightFiles; file_count++) { if (file_count == dWeightFileIndex) { continue; } int num_attempts = 0; const int MAX_ATTEMPTS = 5; dW_time = 0; while (dW_time < simulation_time && num_attempts <= MAX_ATTEMPTS) { pvp_read_header(dWeightsList[file_count], icComm, &dW_time, &filetype, &datatype, params, &numParams); num_attempts++; } // while if (num_attempts > MAX_ATTEMPTS) { fprintf(stderr, "PV::MapReduceKernelConn::reduceKernels: problem reading arbor file %s, SHUTTING DOWN\n", dWeightsList[file_count]); status = EXIT_FAILURE; exit(EXIT_FAILURE); } // num_attempts > MAX_ATTEMPTS int status = PV::readWeights(NULL, get_dwDataStart(), this->numberOfAxonalArborLists(), this->getNumDataPatches(), nxp, nyp, nfp, dWeightsList[file_count], icComm, &dW_time, preLoc); if (status != PV_SUCCESS) { fprintf(stderr, "MapReduceKernelConn::reduceKernels::PV::readWeights: problem reading file %s, " "SHUTTING DOWN\n", dWeightsList[file_count]); exit(EXIT_FAILURE); } // status } // file_count < numWeightFiles // average dW from map-reduce pvwdata_t * dW_data = this->get_dwDataStart(0); for (int i_dW = 0; i_dW < arborSize; i_dW++) { dW_data[i_dW] /= num_dWeightFiles; } } // rootproc // broadcast map-reduced dWeights to all non-root processes MPI_Comm mpi_comm = icComm->communicator(); #ifdef PV_USE_MPI MPI_Bcast(this->get_wDataStart(0), arborSize, MPI_FLOAT, rootproc, mpi_comm); #endif return PV_BREAK; }