int customexit(HyPerCol * hc, int argc, char ** argv) { pvadata_t correctvalue = 0.5f; pvadata_t tolerance = 1.0e-7f; if (hc->columnId()==0) { pvInfo().printf("Checking whether input layer has all values equal to %f ...\n", correctvalue); } HyPerLayer * inputlayer = hc->getLayerFromName("input"); assert(inputlayer); PVLayerLoc const * loc = inputlayer->getLayerLoc(); assert(loc->nf==1); const int numNeurons = inputlayer->getNumNeurons(); assert(numNeurons>0); int status = PV_SUCCESS; int numExtended = inputlayer->getNumExtended(); InterColComm * icComm = hc->icCommunicator(); pvadata_t * layerData = (pvadata_t *) icComm->publisherStore(inputlayer->getLayerId())->buffer(LOCAL); int rootproc = 0; if (icComm->commRank()==rootproc) { pvadata_t * databuffer = (pvadata_t *) malloc(numExtended*sizeof(pvadata_t)); assert(databuffer); for (int proc=0; proc<icComm->commSize(); proc++) { if (proc==rootproc) { memcpy(databuffer, layerData, numExtended*sizeof(pvadata_t)); } else { MPI_Recv(databuffer, numExtended*sizeof(pvadata_t),MPI_BYTE,proc,15,icComm->communicator(), MPI_STATUS_IGNORE); } // At this point, databuffer on rank 0 should contain the extended input layer on rank proc for (int k=0; k<numNeurons; k++) { int kExt = kIndexExtended(k,loc->nx,loc->ny,loc->nf,loc->halo.lt,loc->halo.rt,loc->halo.dn,loc->halo.up); pvadata_t value = databuffer[kExt]; if (fabs(value-correctvalue)>=tolerance) { pvErrorNoExit().printf("Rank %d, restricted index %d, extended index %d, value is %f instead of %f\n", proc, k, kExt, value, correctvalue); status = PV_FAILURE; } } } free(databuffer); if (status == PV_SUCCESS) { pvInfo().printf("%s succeeded.\n", argv[0]); } else { pvError().printf("%s failed.\n", argv[0]); } } else { MPI_Send(layerData,numExtended*sizeof(pvadata_t),MPI_BYTE,rootproc,15,icComm->communicator()); } MPI_Barrier(icComm->communicator()); return status; }
int SegmentLayer::updateState(double timef, double dt) { pvdata_t* srcA = originalLayer->getActivity(); pvdata_t* thisA = getActivity(); assert(srcA); assert(thisA); const PVLayerLoc* loc = getLayerLoc(); //Segment input layer based on segmentMethod if(strcmp(segmentMethod, "none") == 0){ int numBatchExtended = getNumExtendedAllBatches(); //Copy activity over //Since both buffers should be identical size, we can do a memcpy here memcpy(thisA, srcA, numBatchExtended * sizeof(pvdata_t)); } else{ //This case should never happen assert(0); } assert(loc->nf == 1); //Clear centerIdxs for(int bi = 0; bi < loc->nbatch; bi++){ centerIdx[bi].clear(); } for(int bi = 0; bi < loc->nbatch; bi++){ pvdata_t* batchA = thisA + bi * getNumExtended(); //Reset max/min buffers maxX.clear(); maxY.clear(); minX.clear(); minY.clear(); //Loop through this buffer to fill labelVec and idxVec //Looping through restricted, but indices are extended for(int yi = loc->halo.up; yi < loc->ny+loc->halo.up; yi++){ for(int xi = loc->halo.lt; xi < loc->nx+loc->halo.lt; xi++){ //Convert to local extended linear index int niLocalExt = yi * (loc->nx+loc->halo.lt+loc->halo.rt) + xi; //Convert yi and xi to global res index int globalResYi = yi - loc->halo.up + loc->ky0; int globalResXi = xi - loc->halo.lt + loc->kx0; //Get label value //Note that we're assuming that the activity here are integers, //even though the buffer is floats int labelVal = round(batchA[niLocalExt]); //Calculate max/min x and y for a single batch //If labelVal exists in map if(maxX.count(labelVal)){ //Here, we're assuming the 4 maps are in sync, so we use the //.at method, as it will throw an exception as opposed to the //[] operator, which will simply add the key into the map if(globalResXi > maxX.at(labelVal)){ maxX[labelVal] = globalResXi; } if(globalResXi < minX.at(labelVal)){ minX[labelVal] = globalResXi; } if(globalResYi > maxY.at(labelVal)){ maxY[labelVal] = globalResYi; } if(globalResYi < minY.at(labelVal)){ minY[labelVal] = globalResYi; } } //If doesn't exist, add into map with current vals else{ maxX[labelVal] = globalResXi; minX[labelVal] = globalResXi; maxY[labelVal] = globalResYi; minY[labelVal] = globalResYi; } } } //We need to mpi across processors in case a segment crosses an mpi boundary InterColComm * icComm = parent->icCommunicator(); int numMpi = icComm->commSize(); int rank = icComm->commRank(); //Local comm rank //Non root processes simply send buffer size and then buffers int numLabels = maxX.size(); if(rank != 0){ //Load buffers loadLabelBuf(); //Send number of labels first MPI_Send(&numLabels, 1, MPI_INT, 0, rank, icComm->communicator()); //Send labels, then max/min buffers MPI_Send(labelBuf, numLabels, MPI_INT, 0, rank, icComm->communicator()); MPI_Send(maxXBuf, numLabels, MPI_INT, 0, rank, icComm->communicator()); MPI_Send(maxYBuf, numLabels, MPI_INT, 0, rank, icComm->communicator()); MPI_Send(minXBuf, numLabels, MPI_INT, 0, rank, icComm->communicator()); MPI_Send(minYBuf, numLabels, MPI_INT, 0, rank, icComm->communicator()); //Receive the full centerIdxBuf from root process int numCenterIdx = 0; MPI_Bcast(&numCenterIdx, 1, MPI_INT, 0, icComm->communicator()); checkIdxBufSize(numCenterIdx); MPI_Bcast(allLabelsBuf, numCenterIdx, MPI_INT, 0, icComm->communicator()); MPI_Bcast(centerIdxBuf, numCenterIdx, MPI_INT, 0, icComm->communicator()); //Load buffer into centerIdx map loadCenterIdxMap(bi, numCenterIdx); } //Root process stores everything else{ //One recv per buffer for(int recvRank = 1; recvRank < numMpi; recvRank++){ int numRecvLabels = 0; MPI_Recv(&numRecvLabels, 1, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); checkLabelBufSize(numRecvLabels); MPI_Recv(labelBuf, numRecvLabels, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); MPI_Recv(maxXBuf, numRecvLabels, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); MPI_Recv(maxYBuf, numRecvLabels, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); MPI_Recv(minXBuf, numRecvLabels, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); MPI_Recv(minYBuf, numRecvLabels, MPI_INT, recvRank, recvRank, icComm->communicator(), NULL); for(int i = 0; i < numRecvLabels; i++){ int label = labelBuf[i]; //Add on to maps //If the label already exists, fill with proper max/min if(maxX.count(label)){ if(maxXBuf[i] > maxX.at(label)){ maxX[label] = maxXBuf[i]; } if(maxYBuf[i] > maxY.at(label)){ maxY[label] = maxYBuf[i]; } if(minXBuf[i] < minX.at(label)){ minX[label] = minXBuf[i]; } if(minYBuf[i] < minY.at(label)){ minY[label] = minYBuf[i]; } } else{ maxX[label] = maxXBuf[i]; maxY[label] = maxYBuf[i]; minX[label] = minXBuf[i]; minY[label] = minYBuf[i]; } } } //Maps are now filled with all segments from the image //Fill centerIdx based on max/min for(std::map<int, int>::iterator it = maxX.begin(); it != maxX.end(); ++it){ int label = it->first; int centerX = minX.at(label) + (maxX.at(label) - minX.at(label))/2; int centerY = minY.at(label) + (maxY.at(label) - minY.at(label))/2; //Convert centerpoints (in global res idx) to linear idx (in global res space) int centerIdxVal = centerY * (loc->nxGlobal) + centerX; //Add to centerIdxMap centerIdx[bi][label] = centerIdxVal; } //Fill centerpoint buffer int numCenterIdx = centerIdx[bi].size(); checkIdxBufSize(numCenterIdx); int idx = 0; for(std::map<int, int>::iterator it = centerIdx[bi].begin(); it != centerIdx[bi].end(); ++it){ allLabelsBuf[idx] = it->first; centerIdxBuf[idx] = it->second; idx++; } //Broadcast buffers MPI_Bcast(&numCenterIdx, 1, MPI_INT, 0, icComm->communicator()); MPI_Bcast(allLabelsBuf, numCenterIdx, MPI_INT, 0, icComm->communicator()); MPI_Bcast(centerIdxBuf, numCenterIdx, MPI_INT, 0, icComm->communicator()); } } //End batch loop //centerIdx now stores each center coordinate of each segment return PV_SUCCESS; }