void ActionWithVessel::runAllTasks(){ if( getExchangeStep() && nactive_tasks!=fullTaskList.size() ) error("contributors must be unlocked during exchange steps"); plumed_massert( functions.size()>0, "you must have a call to readVesselKeywords somewhere" ); unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); if(serial){ stride=1; rank=0; } // Make sure jobs are done if(timers) stopwatch.start("1 Prepare Tasks"); doJobsRequiredBeforeTaskList(); if(timers) stopwatch.stop("1 Prepare Tasks"); // Get number of threads for OpenMP unsigned nt=OpenMP::getNumThreads(); if( nt*stride*10>nactive_tasks) nt=nactive_tasks/stride/10; if( nt==0 ) nt=1; // Get size for buffer unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); // Clear buffer buffer.assign( buffer.size(), 0.0 ); // Switch off calculation of derivatives in main loop if( dertime_can_be_off ) dertime=false; // std::vector<unsigned> der_list; // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); // Build storage stuff for loop // std::vector<double> buffer( bufsize, 0.0 ); if(timers) stopwatch.start("2 Loop over tasks"); #pragma omp parallel num_threads(nt) { std::vector<double> omp_buffer; if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); myvals.clearAll(); bvals.clearAll(); #pragma omp for nowait for(unsigned i=rank;i<nactive_tasks;i+=stride){ // Calculate the stuff in the loop for this action performTask( indexOfTaskInFullList[i], partialTaskList[i], myvals ); // Weight should be between zero and one plumed_dbg_assert( myvals.get(0)>=0 && myvals.get(0)<=1.0 ); // Check for conditions that allow us to just to skip the calculation // the condition is that the weight of the contribution is low // N.B. Here weights are assumed to be between zero and one if( myvals.get(0)<tolerance ){ // Deactivate task if it is less than the neighbor list tolerance if( myvals.get(0)<nl_tolerance && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); // Clear the derivatives myvals.clearAll(); continue; } // Now calculate all the functions // If the contribution of this quantity is very small at neighbour list time ignore it // untill next neighbour list time if( nt>1 ){ if( !calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ) && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); } else { if( !calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ) && contributorsAreUnlocked ) deactivate_task( indexOfTaskInFullList[i] ); } // Clear the value myvals.clearAll(); } #pragma omp critical if(nt>1) for(unsigned i=0;i<bufsize;++i) buffer[i]+=omp_buffer[i]; } if(timers) stopwatch.stop("2 Loop over tasks"); // Turn back on derivative calculation dertime=true; if(timers) stopwatch.start("3 MPI gather"); // MPI Gather everything if( !serial && buffer.size()>0 ) comm.Sum( buffer ); // MPI Gather index stores if( mydata && !lowmem && !noderiv ){ comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); } // Update the elements that are makign contributions to the sum here // this causes problems if we do it in prepare if( !serial && contributorsAreUnlocked ) comm.Sum( taskFlags ); if(timers) stopwatch.stop("3 MPI gather"); if(timers) stopwatch.start("4 Finishing computations"); finishComputations( buffer ); if(timers) stopwatch.stop("4 Finishing computations"); }
MCMCStepSeq pass(MCMCStepSeq &step, HelperVariables &helpers, Params ¶ms) { int i, j, cp; int bsize1, bsize2, bsize3; double tmp; DoubleVec bmean1(params.kk, 0); DoubleVec bmean2(params.kk, 0); DoubleVec bmean3(params.kk, 0); double bZ1, bZ2, bZ3; IntVec bvals(2); DoubleVec Wvals(2); DoubleVec Bvals(2); DoubleVec bmeanlast(params.kk); double bZlast = 0; // this is used to reference the current block in the MCMCStep we came in with int prevblock = 0; // this is used to reference the current MCMCStep we build from scratch MCMCStepSeq stepnew(step); int currblock = 0; // some other variables to denote stuff in current block and previous block // Note that "last" refers to the immediately left-adjacent block // whereas "prev" refers to the same block in the variable step double thisblockZ = step.bZ[0]; int thisbend = step.bend[0]; double lastblockZ = 0; int lastbend = -1; // this is simply a notational convenience // start the loop for (i = 0; i < params.nn - 1; i++) { if (i == step.bend[prevblock]) { // we're at an old change point, so we need to refresh "this" to be the // immediately following block lastblockZ = thisblockZ; prevblock++; thisbend = step.bend[prevblock]; thisblockZ = step.bZ[prevblock]; } /**** * consider merging blocks if currently a change point */ bvals[0] = stepnew.b; if (step.rho[i] == 0) { // not a change point at the moment Bvals[0] = stepnew.B; Wvals[0] = stepnew.W; } else { // it is a change point, so let's try removing the change point bvals[0]--; tmp = thisblockZ + lastblockZ; bZ3 = 0; if (lastbend > -1) { bsize3 = helpers.cumksize[thisbend] - helpers.cumksize[lastbend]; for (j = 0; j < params.kk; j++) { bmean3[j] = (helpers.cumymat[j][thisbend] - helpers.cumymat[j][lastbend]) / bsize3; bZ3 += pow(bmean3[j], 2) * bsize3; } } else { bsize3 = helpers.cumksize[thisbend]; for (j = 0; j < params.kk; j++) { bmean3[j] = helpers.cumymat[j][thisbend] / bsize3; bZ3 += pow(bmean3[j], 2) * bsize3; } } if (params.kk == 1 && bvals[0] == 1) Bvals[0] = 0; // force this to avoid rounding errs else Bvals[0] = stepnew.B - tmp + bZ3; Wvals[0] = stepnew.W + tmp - bZ3; } /**** * consider breaking blocks if not a change point */ bvals[1] = stepnew.b; if (step.rho[i] == 1) { Bvals[1] = stepnew.B; Wvals[1] = stepnew.W; } else { bZ1 = 0; bZ2 = 0; bvals[1]++; bsize2 = helpers.cumksize[thisbend] - helpers.cumksize[i]; if (lastbend > -1) bsize1 = helpers.cumksize[i] - helpers.cumksize[lastbend]; else bsize1 = helpers.cumksize[i]; tmp = thisblockZ; for (j = 0; j < params.kk; j++) { bmean2[j] = (helpers.cumymat[j][thisbend] - helpers.cumymat[j][i]) / bsize2; if (lastbend > -1) { bmean1[j] = (helpers.cumymat[j][i] - helpers.cumymat[j][lastbend]) / bsize1; } else { bmean1[j] = helpers.cumymat[j][i] / bsize1; } bZ1 += pow(bmean1[j], 2) * bsize1; bZ2 += pow(bmean2[j], 2) * bsize2; } Bvals[1] = stepnew.B - tmp + bZ1 + bZ2; Wvals[1] = stepnew.W + tmp - bZ1 - bZ2; } // if (i == 4122) return(stepnew); double p = getprob(Bvals[0], Bvals[1], Wvals[0], Wvals[1], bvals[0], params); // do the sampling and then updates double myrand = Rf_runif(0.0, 1.0); if (myrand < p) { cp = 1; } else { cp = 0; } // Rprintf("i:%d p=%0.4f, myrand=%0.2f, cp=%d\n", i, p, myrand, cp); stepnew.B = Bvals[cp]; stepnew.W = Wvals[cp]; stepnew.b = bvals[cp]; if (cp != step.rho[i]) { // we modified the change point status if (cp == 0) { // removed a change point // update last block's stuff since the last block is now further back thisblockZ = bZ3; if (currblock > 0) { lastbend = stepnew.bend[currblock - 1]; lastblockZ = stepnew.bZ[currblock - 1]; } else { lastblockZ = 0; lastbend = -1; // this is simply a notational convenience } } else { // added a change point thisblockZ = bZ2; lastblockZ = bZ1; } } stepnew.rho.push_back(cp); if (stepnew.rho[i] == 1) { if (step.rho[i] == 1) { // never calculated these quantities yet; do it now lastblockZ = 0; if (lastbend > -1) bsize1 = helpers.cumksize[i] - helpers.cumksize[lastbend]; else bsize1 = helpers.cumksize[i]; for (j = 0; j < params.kk; j++) { if (lastbend > -1) { bmean1[j] = (helpers.cumymat[j][i] - helpers.cumymat[j][lastbend]) / bsize1; } else { bmean1[j] = helpers.cumymat[j][i] / bsize1; } lastblockZ += pow(bmean1[j], 2) * bsize1; } } // we've added a change point, so we want to record some stuff stepnew.bsize.push_back(bsize1); stepnew.bend.push_back(i); stepnew.bmean.push_back(bmean1); stepnew.bZ.push_back(lastblockZ); currblock++; lastbend = i; } } // done with a full pass, now let's add info on the final block if (lastbend > -1) stepnew.bsize.push_back(params.nn2 - helpers.cumksize[lastbend]); else stepnew.bsize.push_back(params.nn2); for (j = 0; j < params.kk; j++) { if (lastbend > -1) { bmeanlast[j] = (helpers.cumymat[j][params.nn - 1] - helpers.cumymat[j][lastbend]) / stepnew.bsize[currblock]; } else { bmeanlast[j] = helpers.cumymat[j][params.nn - 1] / params.nn2; } bZlast += pow(bmeanlast[j], 2) * stepnew.bsize[currblock]; } stepnew.bmean.push_back(bmeanlast); stepnew.bZ.push_back(bZlast); stepnew.bend.push_back(params.nn - 1); stepnew.rho.push_back(1); return stepnew; }