/********************************************************************** * * Method: isDone() * * Description: check for the software timer to finish. * * Notes: * * Returns: 1 on success, 0 if the timer is running. * **********************************************************************/ int Timer::isDone() { #if 0 if (state != Active) { return (-1); } #endif // // Wait for the timer to expire. // if (state != Done) return 0; timerList.remove(this); // // Restart or idle the timer, depending on its type. // if (type == Periodic) { state = Active; timerList.insert(this); } else { state = Idle; } return 1; } /* isDone() */
int main(int argc, char **argv) { //timer =new TimerList::MyTimer*[ntimers]; int i; //_CrtMemState s1,s2, s3, s4, s5; //_CrtMemCheckpoint( &s1 ); //for ( i = 0; i < ntimers; i++) timer[i]=t.setTimeout((i+1)*1,ding); //for ( i = 0; i < ntimers; i++) t.deleteTimer(i); //_CrtMemCheckpoint( &s2 ); //if ( _CrtMemDifference( &s3, &s1, &s2) ) _CrtMemDumpStatistics( &s3 ); //delete [] timer; timer=NULL; thistimer=t.setInterval(100,ding); t.setInterval(3000,dong); while(1){ t.run(); } return 0; }
/********************************************************************** * * Method: waitfor() * * Description: Wait for the software timer to finish. * * Notes: * * Returns: 0 on success, -1 if the timer is not running. * **********************************************************************/ int Timer::waitfor() { if (state != Active) { return (-1); } // // Wait for the timer to expire. // while (state != Done); timerList.remove(this); // // Restart or idle the timer, depending on its type. // if (type == Periodic) { state = Active; timerList.insert(this); } else { state = Idle; } return (0); } /* waitfor() */
/********************************************************************** * * Method: waitfor() * * Description: Wait for the software timer to finish. * * Notes: * * Returns: 0 on success, -1 if the timer is not running. * **********************************************************************/ int Timer::waitfor() { if (state != Active) { return (-1); } // // Wait for the timer to expire. // pMutex->take(); // // Restart or idle the timer, depending on its type. // if (type == Periodic) { state = Active; timerList.insert(this); } else { pMutex->release(); state = Idle; } return (0); } /* waitfor() */
/********************************************************************** * * Method: start() * * Description: Start a software timer, based on the tick from the * underlying hardware timer. * * Notes: * * Returns: 0 on success, -1 if the timer is already in use. * **********************************************************************/ int Timer::start(unsigned int nMilliseconds, TimerType timerType) { if (state != Idle) { return (-1); } // // Take the mutex. It will be released when the timer expires. // pMutex->take(); // // Initialize the timer. // type = timerType; length = nMilliseconds / MS_PER_TICK; state = Active; // // Add the timer to the timer list. // timerList.insert(this); return (0); } /* start() */
/********************************************************************** * * Method: Interrupt() * * Description: An interrupt handler for the timer hardware. * * Notes: This method is declared static, so that we cannot * inadvertently modify any of the software timers. * * Returns: None defined. * **********************************************************************/ void Timer::Interrupt() { // // Decrement the active timer's count. // timerList.tick(); } /* Interrupt() */
void TimersResponder::replyCreatedId(cTimer* timer, cxxtools::http::Request& request, cxxtools::http::Reply& reply, ostream& out) { QueryHandler q("/timers", request); TimerList* timerList; if ( q.isFormat(".html") ) { reply.addHeader("Content-Type", "text/html; charset=utf-8"); timerList = (TimerList*)new HtmlTimerList(&out); } else if ( q.isFormat(".xml") ) { reply.addHeader("Content-Type", "text/xml; charset=utf-8"); timerList = (TimerList*)new XmlTimerList(&out); } else { reply.addHeader("Content-Type", "application/json; charset=utf-8"); timerList = (TimerList*)new JsonTimerList(&out); } timerList->init(); timerList->addTimer(timer); timerList->setTotal(1); timerList->finish(); delete timerList; }
void CallTimers() { Time now = Time::Now(); while (g_listTimers.GetCount() != 0) { TRef<Timer> ptimer = g_listTimers.GetFront(); if (now < ptimer->m_when) { break; } g_listTimers.PopFront(); if (ptimer->Trigger(now)) { g_listTimers.InsertSorted( new Timer( ptimer->m_psink, ptimer->m_delta, Time::Now() + ptimer->m_delta ) ); } } }
/********************************************************************** * * Method: cancel() * * Description: Stop a running timer. * * Notes: * * Returns: None defined. * **********************************************************************/ void Timer::cancel(void) { // // Remove the timer from the timer list. // if (state == Active) { timerList.remove(this); } // // Reset the timer's state. // state = Idle; } /* cancel() */
/********************************************************************** * * Method: Interrupt() * * Description: An interrupt handler for the timer hardware. * * Notes: This method is declared static, so that we cannot * inadvertently modify any of the software timers. * * Returns: None defined. * **********************************************************************/ void interrupt Timer::Interrupt() { // // Decrement the active timer's count. // timerList.tick(); // // Acknowledge the timer interrupt. // gProcessor.pPCB->intControl.eoi = EOI_NONSPECIFIC; // // Clear the Maximum Count bit (to start the next cycle). // gProcessor.pPCB->timer[2].control &= ~TIMER_MAXCOUNT; } /* Interrupt() */
/********************************************************************** * * Method: start() * * Description: Start a software timer, based on the tick from the * underlying hardware timer. * * Notes: * * Returns: 0 on success, -1 if the timer is already in use. * **********************************************************************/ int Timer::start(unsigned int nMilliseconds, TimerType timerType) { if (state != Idle) { return (-1); } // // Initialize the software timer. // state = Active; type = timerType; length = nMilliseconds / MS_PER_TICK; // // Add the timer to the timer list. // timerList.insert(this); return (0); } /* start() */
void TimersResponder::showTimers(ostream& out, cxxtools::http::Request& request, cxxtools::http::Reply& reply) { QueryHandler q("/timers", request); TimerList* timerList; Timers.SetModified(); if ( q.isFormat(".json") ) { reply.addHeader("Content-Type", "application/json; charset=utf-8"); timerList = (TimerList*)new JsonTimerList(&out); } else if ( q.isFormat(".html") ) { reply.addHeader("Content-Type", "text/html; charset=utf-8"); timerList = (TimerList*)new HtmlTimerList(&out); } else if ( q.isFormat(".xml") ) { reply.addHeader("Content-Type", "text/xml; charset=utf-8"); timerList = (TimerList*)new XmlTimerList(&out); } else { reply.httpReturn(404, "Resources are not available for the selected format. (Use: .json, .html or .xml)"); return; } int start_filter = q.getOptionAsInt("start"); int limit_filter = q.getOptionAsInt("limit"); string timer_id = q.getParamAsString(0); if ( start_filter >= 0 && limit_filter >= 1 ) { timerList->activateLimit(start_filter, limit_filter); } timerList->init(); vector< cTimer* > timers = VdrExtension::SortedTimers(); for (int i=0;i<(int)timers.size();i++) { if ( VdrExtension::getTimerID(timers[i]) == timer_id || timer_id.length() == 0 ) { timerList->addTimer(timers[i]); } } timerList->setTotal((int)timers.size()); timerList->finish(); delete timerList; }
int main(int argc, char** argv) { TimerList tm; tm["total"] = new Timer("[Main] Total runtime for this proc"); tm["grid"] = new Timer("[Main] Grid generation"); tm["stencils"] = new Timer("[Main] Stencil generation"); tm["settings"] = new Timer("[Main] Load settings"); tm["decompose"] = new Timer("[Main] Decompose domain"); tm["consolidate"] = new Timer("[Main] Consolidate subdomain solutions"); tm["updates"] = new Timer("[Main] Broadcast solution updates"); tm["send"] = new Timer("[Main] Send subdomains to other processors (master only)"); tm["receive"] = new Timer("[Main] Receive subdomain from master (clients only)"); tm["timestep"] = new Timer("[Main] Advance One Timestep"); tm["tests"] = new Timer("[Main] Test stencil weights"); tm["weights"] = new Timer("[Main] Compute all stencils weights"); tm["oneWeight"] = new Timer("[Main] Compute single stencil weights"); tm["heat_init"] = new Timer("[Main] Initialize heat"); // grid should only be valid instance for MASTER Grid* grid = NULL; Domain* subdomain; tm["total"]->start(); Communicator* comm_unit = new Communicator(argc, argv); cout << " Got Rank: " << comm_unit->getRank() << endl; cout << " Got Size: " << comm_unit->getSize() << endl; tm["settings"]->start(); ProjectSettings* settings = new ProjectSettings(argc, argv, comm_unit->getRank()); int dim = settings->GetSettingAs<int>("DIMENSION", ProjectSettings::required); //----------------- fillGlobalProjectSettings(dim, settings); //----------------- int max_num_iters = settings->GetSettingAs<int>("MAX_NUM_ITERS", ProjectSettings::required); double max_global_rel_error = settings->GetSettingAs<double>("MAX_GLOBAL_REL_ERROR", ProjectSettings::optional, "1e-1"); double max_local_rel_error = settings->GetSettingAs<double>("MAX_LOCAL_REL_ERROR", ProjectSettings::optional, "1e-1"); int use_gpu = settings->GetSettingAs<int>("USE_GPU", ProjectSettings::optional, "1"); int local_sol_dump_frequency = settings->GetSettingAs<int>("LOCAL_SOL_DUMP_FREQUENCY", ProjectSettings::optional, "100"); int global_sol_dump_frequency = settings->GetSettingAs<int>("GLOBAL_SOL_DUMP_FREQUENCY", ProjectSettings::optional, "200"); int prompt_to_continue = settings->GetSettingAs<int>("PROMPT_TO_CONTINUE", ProjectSettings::optional, "0"); int debug = settings->GetSettingAs<int>("DEBUG", ProjectSettings::optional, "0"); double start_time = settings->GetSettingAs<double>("START_TIME", ProjectSettings::optional, "0.0"); double end_time = settings->GetSettingAs<double>("END_TIME", ProjectSettings::optional, "1.0"); double dt = settings->GetSettingAs<double>("DT", ProjectSettings::optional, "1e-5"); int timescheme = settings->GetSettingAs<int>("TIME_SCHEME", ProjectSettings::optional, "1"); int weight_method = settings->GetSettingAs<int>("WEIGHT_METHOD", ProjectSettings::optional, "1"); int compute_eigenvalues = settings->GetSettingAs<int>("DERIVATIVE_EIGENVALUE_TEST", ProjectSettings::optional, "0"); int use_eigen_dt = settings->GetSettingAs<int>("USE_EIGEN_DT", ProjectSettings::optional, "1"); if (comm_unit->isMaster()) { int ns_nx = settings->GetSettingAs<int>("NS_NB_X", ProjectSettings::optional, "10"); int ns_ny = settings->GetSettingAs<int>("NS_NB_Y", ProjectSettings::optional, "10"); int ns_nz = settings->GetSettingAs<int>("NS_NB_Z", ProjectSettings::optional, "10"); int stencil_size = settings->GetSettingAs<int>("STENCIL_SIZE", ProjectSettings::required); tm["settings"]->stop(); grid = getGrid(dim); grid->setMaxStencilSize(stencil_size); Grid::GridLoadErrType err = grid->loadFromFile(); if (err == Grid::NO_GRID_FILES) { printf("************** Generating new Grid **************\n"); //grid->setSortBoundaryNodes(true); // grid->setSortBoundaryNodes(true); tm["grid"]->start(); grid->generate(); tm["grid"]->stop(); grid->writeToFile(); } if ((err == Grid::NO_GRID_FILES) || (err == Grid::NO_STENCIL_FILES)) { std::cout << "Generating stencils files\n"; tm["stencils"]->start(); grid->setNSHashDims(ns_nx, ns_ny, ns_nz); // grid->generateStencils(Grid::ST_BRUTE_FORCE); // DEFINTELY: exact grid->generateStencils(Grid::ST_KDTREE); // MIGHT BE: approximate // grid->generateStencils(Grid::ST_HASH); tm["stencils"]->stop(); grid->writeToFile(); tm.writeToFile("gridgen_timer_log"); } int x_subdivisions = comm_unit->getSize(); // reduce this to impact y dimension as well int y_subdivisions = (comm_unit->getSize() - x_subdivisions) + 1; // TODO: load subdomain from disk // Construct a new domain given a grid. // TODO: avoid filling sets Q, B, etc; just think of it as a copy constructor for a grid Domain* original_domain = new Domain(dim, grid, comm_unit->getSize()); // pre allocate pointers to all of the subdivisions std::vector<Domain*> subdomain_list(x_subdivisions*y_subdivisions); // allocate and fill in details on subdivisions std::cout << "Generating subdomains\n"; tm["decompose"]->start(); //original_domain->printVerboseDependencyGraph(); original_domain->generateDecomposition(subdomain_list, x_subdivisions, y_subdivisions); tm["decompose"]->stop(); tm["send"]->start(); subdomain = subdomain_list[0]; for (int i = 1; i < comm_unit->getSize(); i++) { std::cout << "Sending subdomain[" << i << "]\n"; comm_unit->sendObject(subdomain_list[i], i); } tm["send"]->stop(); printf("----------------------\nEND MASTER ONLY\n----------------------\n\n\n"); } else { tm["settings"]->stop(); cout << "MPI RANK " << comm_unit->getRank() << ": waiting to receive subdomain" << endl; tm["receive"]->start(); subdomain = new Domain(); // EMPTY object that will be filled by MPI comm_unit->receiveObject(subdomain, 0); // Receive from CPU (0) tm["receive"]->stop(); } comm_unit->barrier(); if (debug) { subdomain->printVerboseDependencyGraph(); subdomain->printNodeList("All Centers Needed by This Process"); printf("CHECKING STENCILS: "); for (int irbf = 0; irbf < (int)subdomain->getStencilsSize(); irbf++) { // printf("Stencil[%d] = ", irbf); StencilType& s = subdomain->getStencil(irbf); if (irbf == s[0]) { // printf("PASS\n"); // subdomain->printStencil(s, "S"); } else { printf("FAIL on stencil %d\n", irbf); exit(EXIT_FAILURE); } } printf("OK\n"); } RBFFD* der; if (use_gpu) { der = new RBFFD_CL(RBFFD::LAPL | RBFFD::X | RBFFD::Y | RBFFD::Z, subdomain, dim, comm_unit->getRank()); } else { der = new RBFFD(RBFFD::LAPL | RBFFD::X | RBFFD::Y | RBFFD::Z, subdomain, dim, comm_unit->getRank()); } int use_var_eps = settings->GetSettingAs<int>("USE_VAR_EPSILON", ProjectSettings::optional, "0"); if (use_var_eps) { double alpha = settings->GetSettingAs<double>("VAR_EPSILON_ALPHA", ProjectSettings::optional, "1.0"); double beta = settings->GetSettingAs<double>("VAR_EPSILON_BETA", ProjectSettings::optional, "1.0"); //der->setVariableEpsilon(subdomain->getStencilRadii(), subdomain->getStencils(), alpha, beta); der->setVariableEpsilon(alpha, beta); } else { double epsilon = settings->GetSettingAs<double>("EPSILON", ProjectSettings::required); der->setEpsilon(epsilon); } #if 0 der->setWeightType(RBFFD::ContourSVD); der->setWeightType(RBFFD::Direct); #else der->setWeightType((RBFFD::WeightType)weight_method); #endif // Try loading all the weight files int err = der->loadFromFile(RBFFD::X); err += der->loadFromFile(RBFFD::Y); err += der->loadFromFile(RBFFD::Z); err += der->loadFromFile(RBFFD::LAPL); if (err) { printf("start computing weights\n"); tm["weights"]->start(); // NOTE: good test for Direct vs Contour // Grid 11x11, vareps=0.05; Look at stencil 12. SHould have -100, 25, // 25, 25, 25 (i.e., -4,1,1,1,1) not sure why scaling is off. der->computeAllWeightsForAllStencils(); tm["weights"]->stop(); cout << "end computing weights" << endl; der->writeToFile(RBFFD::X); der->writeToFile(RBFFD::Y); der->writeToFile(RBFFD::Z); der->writeToFile(RBFFD::LAPL); cout << "end write weights to file" << endl; } if (settings->GetSettingAs<int>("RUN_DERIVATIVE_TESTS", ProjectSettings::optional, "1")) { bool weightsPreComputed = true; bool exitIfTestFailed = settings->GetSettingAs<int>("BREAK_ON_DERIVATIVE_TESTS", ProjectSettings::optional, "1"); tm["tests"]->start(); // The test class only computes weights if they havent been done already DerivativeTests* der_test = new DerivativeTests(dim, der, subdomain, weightsPreComputed); if (use_gpu) { // Applies weights on both GPU and CPU and compares results for the first 10 stencils der_test->compareGPUandCPUDerivs(10); } // Test approximations to derivatives of functions f(x,y,z) = 0, x, y, xy, etc. etc. der_test->testAllFunctions(exitIfTestFailed); // For now we can only test eigenvalues on an MPI size of 1 (we could distribute with Par-Eiegen solver) if (comm_unit->getSize() == 1) { if (compute_eigenvalues) { // FIXME: why does this happen? Perhaps because X Y and Z are unidirectional? // Test X and 4 eigenvalues are > 0 // Test Y and 30 are > 0 // Test Z and 36 are > 0 // NOTE: the 0 here implies we compute the eigenvalues but do not run the iterations of the random perturbation test der_test->testEigen(RBFFD::LAPL, 0); } } tm["tests"]->stop(); } // SOLVE HEAT EQUATION ExactSolution* exact = getExactSolution(dim); TimeDependentPDE* pde; tm["heat_init"]->start(); // We need to provide comm_unit to pass ghost node info #if 0 if (use_gpu) { pde = new HeatPDE(subdomain, der, comm_unit, true); } else #endif { // Implies initial conditions are generated // true here indicates the weights are computed. pde = new HeatPDE(subdomain, der, comm_unit, uniformDiffusion, true); } pde->setStartEndTime(start_time, end_time); pde->fillInitialConditions(exact); // Broadcast updates for timestep, initial conditions for ghost nodes, etc. tm["updates"]->start(); comm_unit->broadcastObjectUpdates(pde); comm_unit->barrier(); tm["updates"]->stop(); tm["heat_init"]->stop(); //TODO: pde->setRelErrTol(max_global_rel_error); // Setup a logging class that will monitor our iteration and dump intermediate files #if USE_VTK // TODO: update VtuPDEWriter for the new PDE classes PDEWriter* writer = new VtuPDEWriter(subdomain, pde, comm_unit, local_sol_dump_frequency, global_sol_dump_frequency); #else PDEWriter* writer = new PDEWriter(subdomain, pde, comm_unit, local_sol_dump_frequency, global_sol_dump_frequency); #endif // Test DT: // 1) get the minimum avg stencil radius (for stencil area--i.e., dx^2) double avgdx = 1000.; std::vector<StencilType>& sten = subdomain->getStencils(); for (size_t i=0; i < sten.size(); i++) { double dx = subdomain->getStencilRadius(i); if (dx < avgdx) { avgdx = dx; } } // Laplacian = d^2/dx^2 double sten_area = avgdx*avgdx; // Not sure where Gordon came up with this parameter. // for second centered difference and euler time we have nu = 0.5 double nu = 0.1; // dt <= nu/dx^2 // is valid for stability in some FD schemes. double max_dt = nu*(sten_area); printf("dt = %f (max_dt = %f; 0.5dx^2 = %f)\n", dt, max_dt, 0.5*sten_area); // This appears to be consistent with Chinchipatnam2006 (Thesis) // TODO: get more details on CFL for RBFFD // note: checking stability only works if we have all weights for all // nodes, so we dont do it in parallel if (compute_eigenvalues && (comm_unit->getSize() == 1)) { RBFFD::EigenvalueOutput eigs = der->getEigenvalues(); max_dt = 2. / eigs.max_neg_eig; printf("Suggested max_dt based on eigenvalues (2/lambda_max)= %f\n", max_dt); // CFL condition: if (dt > max_dt) { std::cout << "WARNING! your choice of timestep (" << dt << ") is TOO LARGE for to maintain stability of system. According to eigenvalues, it must be less than " << max_dt << std::endl; if (use_eigen_dt) { dt = max_dt; } else { //exit(EXIT_FAILURE); } } } std::cout << "[MAIN] ********* USING TIMESTEP dt=" << dt << " ********** " << std::endl; // subdomain->printCenterMemberships(subdomain->G, "G = " ); //subdomain->printBoundaryIndices("INDICES OF GLOBAL BOUNDARY NODES: "); int iter; int num_iters = (int) ((end_time - start_time) / dt); std::cout << "NUM_ITERS = " << num_iters << std::endl; for (iter = 0; iter < num_iters && iter < max_num_iters; iter++) { writer->update(iter); #if 0 char label[256]; sprintf(label, "LOCAL INPUT SOLUTION [local_indx (global_indx)] FOR ITERATION %d", iter); pde->printSolution(label); #endif tm["timestep"]->start(); pde->advance((TimeDependentPDE::TimeScheme)timescheme, dt); tm["timestep"]->stop(); // This just double checks that all procs have ghost node info. // pde->advance(..) should broadcast intermediate updates as needed, // but updated solution. tm["updates"]->start(); comm_unit->broadcastObjectUpdates(pde); comm_unit->barrier(); tm["updates"]->stop(); if (!(iter % local_sol_dump_frequency)) { std::cout << "\n*********** Rank " << comm_unit->getRank() << " Local Solution [ Iteration: " << iter << " (t = " << pde->getTime() << ") ] *************" << endl; pde->checkLocalError(exact, max_local_rel_error); } if (!(iter % global_sol_dump_frequency)) { tm["consolidate"]->start(); comm_unit->consolidateObjects(pde); comm_unit->barrier(); tm["consolidate"]->stop(); if (comm_unit->isMaster()) { std::cout << "\n*********** Global Solution [ Iteration: " << iter << " (t = " << pde->getTime() << ") ] *************" << endl; pde->checkGlobalError(exact, grid, max_global_rel_error); } } #if 0 sprintf(label, "LOCAL UPDATED SOLUTION [local_indx (global_indx)] AFTER %d ITERATIONS", iter+1); pde->printSolution(label); #endif // double nrm = pde->maxNorm(); if (prompt_to_continue && comm_unit->isMaster()) { std::string buf; cout << "Press [Enter] to continue" << std::endl; cin.get(); } } #if 1 printf("after heat\n"); // NOTE: all local subdomains have a U_G solution which is consolidated // into the MASTER process "global_U_G" solution. tm["consolidate"]->start(); comm_unit->consolidateObjects(pde); comm_unit->barrier(); tm["consolidate"]->stop(); // subdomain->writeGlobalSolutionToFile(-1); std::cout << "Checking Solution on Master\n"; if (comm_unit->getRank() == 0) { pde->writeGlobalGridAndSolutionToFile(grid->getNodeList(), (char*) "FINAL_SOLUTION.txt"); #if 0 // NOTE: the final solution is assembled, but we have to use the // GLOBAL node list instead of a local subdomain node list cout << "FINAL ITER: " << iter << endl; std::vector<double> final_sol(grid->getNodeListSize()); ifstream fin; fin.open("FINAL_SOLUTION.txt"); int count = 0; for (int count = 0; count < final_sol.size(); count++) { Vec3 node; double val; fin >> node[0] >> node[1] >> node[2] >> val; if (fin.good()) { final_sol[count] = val; // std::cout << "Read: " << node << ", " << final_sol[count] << std::endl; } } fin.close(); #endif std::cout << "============== Verifying Accuracy of Final Solution =============\n"; pde->checkGlobalError(exact, grid, max_global_rel_error); std::cout << "============== Solution Valid =============\n"; delete(grid); }
void Window::RemoveSink(IEventSink* psink) { g_listTimers.Remove(new Timer(psink, 0, 0)); }
void Window::AddSink(IEventSink* psink, float delta) { g_listTimers.InsertSorted(new Timer(psink, delta, Time::Now() + delta)); }