void ThreadRunManager::run(Manager::RunMode mode) { threads_.clear(); // lamda auto func = [&](const QList<Worker*> workers){ auto thread = new CustomThread(workers); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); connect(thread, SIGNAL(finished()), SLOT(finished())); connect(this, SIGNAL(pauseWorker()), thread, SLOT(workCancel()), Qt::DirectConnection); thread->start(); threads_ << thread; }; if (mode == RunSeries) { func(workers()); } else { QList<Worker*> workerLists[ThreadCount]; for (int i = 0; i < workers().size(); ++i) { workerLists[i % ThreadCount] << workers().at(i); } for (int i = 0; i < ThreadCount; ++i) { func(workerLists[i]); } } }
CharString NounStructure::status() const { CharString info; info += "\n"; if ( damage() > 0 ) info += CharString().format("<color;0000ff>DAMAGE: %d%%</color>\n", (damage() * 100) / maxDamage() ); if ( workers() != 0 ) info += CharString().format( "Workers: %s\n", FormatNumber<char,int>( -workers() ).cstr() ); if ( power() != 0 ) info += CharString().format( "Power: %s\n", FormatNumber<char,int>( power() ).cstr() ); if ( technology() != 0 ) info += CharString().format( "Technology: %d\n", technology() ); if ( upkeep() != 0 ) info += CharString().format( "Upkeep: %d\n", upkeep() ); if ( active() ) { if ( food() != 0 ) info += CharString().format( "Food: %s\n", FormatNumber<char,int>( food() ).cstr() ); if ( habitat() != 0 ) info += CharString().format( "Habitat: %s\n", FormatNumber<char,int>( habitat() ).cstr() ); if ( mining() != 0 ) info += CharString().format( "Mining: %s\n", FormatNumber<char,int>( mining() ).cstr() ); if ( research() != 0 ) info += CharString().format( "Research: %s\n", FormatNumber<char,int>( research() ).cstr() ); if ( production() != 0 ) info += CharString().format( "Production: %s\n", FormatNumber<char,int>( production() ).cstr() ); if ( protection() != 0.0f ) info += CharString().format( "PD: %d%%\n", (int)(protection() * 100) ); } else if ( flags() & FLAG_ACTIVE ) { if ( flags() & FLAG_WORKER_SHORT ) info += "<color;0000ff>WORKER SHORTAGE!</color>\n"; if ( flags() & FLAG_POWER_SHORT ) info += "<color;0000ff>POWER SHORTAGE!</color>\n"; if ( flags() & FLAG_TECH_SHORT ) info += "<color;0000ff>TECHNOLOGY SHORTAGE!</color>\n"; } else { info += "\n<color;ffffff>INACTIVE</color>\n"; } if ( isBuilding() ) info += CharString().format("\nBuilding...%d%% complete\n", buildComplete() ); return info; }
Int_t mp001_fillHistos(UInt_t nWorkers = 4) { // Total amount of numbers const UInt_t nNumbers = 20000000U; // We define our work item auto workItem = [nNumbers](UInt_t workerID) { // One generator, file and ntuple per worker TRandom3 workerRndm(workerID); // Change the seed TFile f(Form("myFile_%u.root", workerID), "RECREATE"); TH1F h(Form("myHisto_%u", workerID), "The Histogram", 64, -4, 4); for (UInt_t i = 0; i < nNumbers; ++i) { h.Fill(workerRndm.Gaus()); } h.Write(); return 0; }; // Create the pool of workers TProcPool workers(nWorkers); // Fill the pool with work std::forward_list<UInt_t> workerIDs(nWorkers); std::iota(std::begin(workerIDs), std::end(workerIDs), 0); workers.Map(workItem, workerIDs); return 0; }
int main () { // One I/O thread in the thread pool will do. zmq::context_t ctx (1); // Create an endpoint for worker threads to connect to. // We are using XREQ socket so that processing of one request // won't block other requests. zmq::socket_t workers (ctx, ZMQ_XREQ); workers.bind ("inproc://workers"); // Create an endpoint for client applications to connect to. // We are usign XREP socket so that processing of one request // won't block other requests. zmq::socket_t clients (ctx, ZMQ_XREP); clients.bind ("tcp://lo:5555"); // We'll use 11 application threads. Main thread will be used to run // 'dispatcher' (queue). Aside of that there'll be 10 worker threads. // Launch 10 worker threads. for (int i = 0; i != 10; i++) { pthread_t worker; int rc = pthread_create (&worker, NULL, worker_routine, (void*) &ctx); assert (rc == 0); } // Use queue device as a dispatcher of messages from clients to worker // threads. zmq::device (ZMQ_QUEUE, clients, workers); return 0; }
void World::updateAllInParallel(int stepsize) { auto worker_func = [] (auto begin, auto end, int stepsize) { for(auto updatable_iter = begin; updatable_iter != end; ++updatable_iter) { (*updatable_iter)->step(stepsize); } } ; static const unsigned num_workers = std::thread::hardware_concurrency(); unsigned per_worker = updatable_ptrs_.size() / num_workers; auto chunk_start = updatable_ptrs_.begin(); std::vector<std::thread> workers(num_workers); for(auto w = workers.begin(); w != workers.end() - 1; ++w) { *w = std::thread(worker_func, chunk_start, chunk_start + per_worker, stepsize); chunk_start += per_worker; } // set last worker's end iterator to .end() in case per_worker is not even workers.back() = std::thread(worker_func, chunk_start, updatable_ptrs_.end(), stepsize); for(auto&& w : workers) w.join(); }
/* * Statistics */ Statistics DFS::statistics(void) const { Statistics s; for (unsigned int i=0; i<workers(); i++) s += worker(i)->statistics(); return s; }
void NCCL<Dtype>::Run(const vector<int>& gpus, const char* restore) { boost::barrier barrier(static_cast<int>(gpus.size())); vector<NCCL<Dtype>*> nccls(gpus.size()); // Create workers vector<shared_ptr<Worker<Dtype> > > workers(gpus.size()); for (int i = 1; i < gpus.size(); ++i) { CUDA_CHECK(cudaSetDevice(gpus[i])); Caffe::set_solver_rank(i); Worker<Dtype>* w = new Worker<Dtype>(solver_, gpus[i], &barrier, &nccls, restore); w->StartInternalThread(); workers[i].reset(w); } CUDA_CHECK(cudaSetDevice(gpus[0])); Caffe::set_solver_rank(0); barrier_ = &barrier; solver_->add_callback(this); if (solver_->param().layer_wise_reduce()) { solver_->net()->add_after_backward(this); } nccls[0] = this; // Wait for workers barrier.wait(); // Init NCCL InitSingleProcess(&nccls); barrier.wait(); // Run first solver on current thread Broadcast(); solver_->Solve(); barrier.wait(); // Hangs without it when running tests // Wait for shutdown for (int i = 1; i < gpus.size(); ++i) { workers[i]->StopInternalThread(); } }
int main(int argc, char *argv[]) { if (!init(argc, argv)) exit(0); std::cout << "Starting prime server with " << g_conf_threads << " worker thread(s)" << std::endl; std::cout << "Listening on port " << g_conf_port << std::endl; // Prepare ZMQ context and sockets zmq::context_t context(1); zmq::socket_t clients (context, ZMQ_ROUTER); char bind_str[20]; sprintf(bind_str, "tcp://*:%d", g_conf_port); clients.bind (bind_str); zmq::socket_t workers (context, ZMQ_DEALER); workers.bind ("inproc://workers"); // Launch pool of worker threads for (uint8_t thread_nbr = 0; thread_nbr != g_conf_threads; thread_nbr++) { pthread_t worker; pthread_create(&worker, NULL, worker_thread, (void *) &context); } // Connect work threads to client threads via a queue zmq::proxy(static_cast<void *>(clients), static_cast<void *>(workers), NULL); return 0; }
void PoolManager::run(Manager::RunMode mode) { QThreadPool::globalInstance()->setMaxThreadCount(mode == RunSeries ? 1 : ThreadCount); for (auto w : workers()) QThreadPool::globalInstance()->start(new Runnable(w)); }
void QtEventWorkerFactory:: test() { std::string name = "QtEventWorkers"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); // takes 0.4 s if this is the first instantiation of QApplication Workers::test ([](ISchedule::ptr schedule){ Bedroom::ptr bedroom(new Bedroom); return IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom)); }); { UNITTEST_STEPS TaskInfo("It should terminate all threads when it's closed"); ISchedule::ptr schedule[] = { ISchedule::ptr(new SleepScheduleMock), ISchedule::ptr(new LockScheduleMock), ISchedule::ptr(new BusyScheduleMock) }; for (unsigned i=0; i<sizeof(schedule)/sizeof(schedule[0]); i++) { Timer t; { ISchedule::ptr s = schedule[i]; //TaskInfo ti(boost::format("%s") % vartype(*s)); Bedroom::ptr bedroom(new Bedroom); Processing::Workers workers(IWorkerFactory::ptr(new QtEventWorkerFactory(s, bedroom))); Bedroom::Bed bed = dynamic_cast<BlockScheduleMock*>(s.get ())->bedroom.getBed(); workers.addComputingEngine(Signal::ComputingEngine::ptr()); // Wait until the schedule has been called (Bedroom supports // that the wakeup in schedule is called even before this sleep call // as long as 'bed' is allocated before the wakeup call) bed.sleep (); EXCEPTION_ASSERT_EQUALS(false, workers.remove_all_engines (10)); EXCEPTION_ASSERT_EQUALS(true, QtEventWorkerFactory::terminate_workers (workers, 0)); EXCEPTION_ASSERT_EQUALS(workers.n_workers(), 0u); EXPECT_EXCEPTION(QtEventWorker::TerminatedException, workers.rethrow_any_worker_exception ()); workers.clean_dead_workers (); } float elapsed = t.elapsed (); float n = (i+1)*0.00001; EXCEPTION_ASSERT_LESS(0.01+n, elapsed); EXCEPTION_ASSERT_LESS(elapsed, 0.04+n); // +n makes it possible to see in the test log which iteration that failed } } // It should wake up sleeping workers when any work is done to see if they can // help out on what's left. { } }
void Master::step(const std::vector<unsigned>& fstim) { m_timer.step(); #ifdef NEMO_MPI_DEBUG_TIMING m_mpiTimer.reset(); #endif unsigned wcount = workers(); std::vector<SimulationStep> oreqData(wcount); std::vector<boost::mpi::request> oreqs(wcount); distributeFiringStimulus(m_mapper, fstim, oreqData); #ifdef NEMO_MPI_DEBUG_TIMING m_mpiTimer.substep(); #endif for(unsigned r=0; r < wcount; ++r) { oreqs.at(r) = m_world.isend(r+1, MASTER_STEP, oreqData.at(r)); } #ifdef NEMO_MPI_DEBUG_TIMING m_mpiTimer.substep(); #endif boost::mpi::wait_all(oreqs.begin(), oreqs.end()); #ifdef NEMO_MPI_DEBUG_TIMING m_mpiTimer.substep(); #endif m_firing.push_back(std::vector<unsigned>()); std::vector<unsigned> dummy_fired; std::vector< std::vector<unsigned> > fired; gather(m_world, dummy_fired, fired, MASTER); /* If neurons are allocated to nodes ordered by neuron index, we can get a * sorted list by just concatening the per-node lists in rank order */ for(unsigned r=0; r < wcount; ++r) { const std::vector<unsigned>& node_fired = fired.at(r+1); std::copy(node_fired.begin(), node_fired.end(), std::back_inserter(m_firing.back())); #ifdef NEMO_MPI_DEBUG_TRACE MPI_LOG("Master received %u firings from %u\n", node_fired.size(), r+1); #endif } #ifdef NEMO_MPI_DEBUG_TRACE std::copy(m_firing.back().begin(), m_firing.back().end(), std::ostream_iterator<unsigned>(std::cout, " ")); #endif #ifdef NEMO_MPI_DEBUG_TIMING m_mpiTimer.substep(); m_mpiTimer.step(); #endif }
/* * Perform reset * */ void DFS::reset(Space* s) { // Grab wait lock for reset m_wait_reset.acquire(); // Release workers for reset release(C_RESET); // Wait for reset cycle started e_reset_ack_start.wait(); // All workers are marked as busy again n_busy = workers(); for (unsigned int i=1U; i<workers(); i++) worker(i)->reset(NULL,0); worker(0U)->reset(s,opt().nogoods_limit); // Block workers again to ensure invariant block(); // Release reset lock m_wait_reset.release(); // Wait for reset cycle stopped e_reset_ack_stop.wait(); }
/** * スレッドを使用しない。 * * modeがRunParallelの時は * ワーカ切り替え時のみイベント処理を回す。 */ void NoThreadManger::run(RunMode mode) { for (auto w : workers()) { if (stop()) break; w->doWork(); if (mode == RunParallel) qApp->processEvents(); } }
void Master::terminate() { unsigned wcount = workers(); SimulationStep data(true, std::vector<unsigned>()); std::vector<boost::mpi::request>reqs(wcount); for(unsigned r=0; r < wcount; ++r) { reqs[r] = m_world.isend(r+1, MASTER_STEP, data); } boost::mpi::wait_all(reqs.begin(), reqs.end()); }
/* ======================== TestWorkers ======================== */ void TestWorkers() { idSysWorkerThreadGroup<idMyThread> workers( "myWorkers", 4 ); for( ; ; ) { for( int i = 0; i < workers.GetNumThreads(); i++ ) { // workers.GetThread( i )-> // setup work for this thread } workers.SignalWorkAndWait(); } }
Int_t mp102_readNtuplesFillHistosAndFit() { // No nuisance for batch execution gROOT->SetBatch(); // Perform the operation sequentially --------------------------------------- TChain inputChain("multiCore"); inputChain.Add("mp101_multiCore_*.root"); TH1F outHisto("outHisto", "Random Numbers", 128, -4, 4); { TimerRAII t("Sequential read and fit"); inputChain.Draw("r >> outHisto"); outHisto.Fit("gaus"); } // We now go MP! ------------------------------------------------------------ // TProcPool offers an interface to directly process trees and chains without // the need for the user to go through the low level implementation of a // map-reduce. // We adapt our parallelisation to the number of input files const auto nFiles = inputChain.GetListOfFiles()->GetEntries(); // This is the function invoked during the processing of the trees. auto workItem = [](TTreeReader & reader) { TTreeReaderValue<Float_t> randomRV(reader, "r"); auto partialHisto = new TH1F("outHistoMP", "Random Numbers", 128, -4, 4); while (reader.Next()) { partialHisto->Fill(*randomRV); } return partialHisto; }; // Create the pool of processes TProcPool workers(nFiles); // Process the TChain { TimerRAII t("Parallel execution"); TH1F *sumHistogram = workers.ProcTree(inputChain, workItem, "multiCore"); sumHistogram->Fit("gaus", 0); } return 0; }
int main() { boost::thread_group g; std::vector<Worker> workers(10); std::vector<size_t> responses_received(workers.size()); for (auto& w : workers) g.create_thread(boost::ref(w)); // let's given them something to do const auto num_requests = (1ul<<20); std::string response; for (size_t i = 0; i < num_requests; ++i) { // send to a random worker auto& w = workers[rand()%workers.size()]; w.incoming->push("request " + std::to_string(i)); // scheduled processing of responses int round_robin = i%workers.size(); if (workers[round_robin].outgoing->pop(response)) { ++responses_received[round_robin]; } } auto const sum = std::accumulate(begin(responses_received), end(responses_received), size_t()); std::cout << "\nReceived " << sum << " responses ("; std::copy(begin(responses_received), end(responses_received), std::ostream_iterator<size_t>(std::cout, " ")); std::cout << ")\n"; shutdown = true; g.join_all(); size_t late_arrivals = 0; for (auto& w : workers) { while (w.outgoing->pop(response)) { ++late_arrivals; } } std::cout << "\nLate arrivals: " << late_arrivals << " (total: " << (sum + late_arrivals) << " responses/" << num_requests << " requests)\n"; }
int main () { // Prepare our context and sockets zmq::context_t context (1); zmq::socket_t clients (context, ZMQ_ROUTER); clients.bind ("tcp://*:5555"); zmq::socket_t workers (context, ZMQ_DEALER); workers.bind ("inproc://workers"); // Launch pool of worker threads for (int thread_nbr = 0; thread_nbr != 5; thread_nbr++) { pthread_t worker; pthread_create (&worker, NULL, worker_routine, (void *) &context); } // Connect work threads to client threads via a queue zmq::device (ZMQ_QUEUE, clients, workers); return 0; }
int main() { std::srand(std::time(0)); boost::asio::io_service ios; boost::asio::zmq::context ctx; std::vector<std::unique_ptr<req_worker>> workers(NBR_WORKERS); for (int worker_nbr = 0; worker_nbr < NBR_WORKERS; worker_nbr++) { workers[worker_nbr].reset(new req_worker(ios, ctx, worker_nbr)); workers[worker_nbr]->start(); } client c(ios, ctx); c.start(); ios.run(); return 0; }
int Comp2::c2method( int input){ // Prepare our context and sockets zmq::context_t context (1); zmq::socket_t clients (context, ZMQ_ROUTER); clients.bind ("tcp://0.0.0.0:8123"); zmq::socket_t workers (context, ZMQ_DEALER); workers.bind ("inproc://workers"); // Launch pool of worker threads for (int thread_nbr = 0; thread_nbr != 10; thread_nbr++) { pthread_t worker; pthread_create (&worker, NULL, worker_routine, (void *) &context); } // Connect work threads to client threads via a queue zmq::proxy ((void *)clients, (void *)workers, NULL); return input * 4; }
/** * Test program simulating; multiple threads consuming * stack datastructure */ int main(int argc, char **argv) { // allocate a worker pool to similuate multi-thread enviornment WorkerPool workers(4); int numOperations = 100; Stack<int> s(5); for (int i = 0; i < numOperations; ++i) { workers.publish([&s, i]() { s.push(i); std::cout << ":push: " << i << "\n"; std::cout << ":pop: " << s.pop() << "\n"; }); } workers.waitForDrain(); std::cout << "All task done!\n"; return 0; }
int main( int argc, char **argv ){ zmq::context_t ctx(2); zmq::socket_t workers( ctx, ZMQ_XREQ ); workers.bind( "inproc://workers" ); zmq::socket_t clients( ctx, ZMQ_XREP ); clients.bind( "tcp://*:5555" ); std::cout << "Starting worker threads..." << std::endl; for( size_t i = 0 ; i < 10 ; ++i ){ pthread_t worker; int rc = pthread_create( &worker, NULL, suisto_worker, (void*)&ctx ); } std::cout << "Starting queue..." << std::endl << std::endl; zmq::device( ZMQ_QUEUE, clients, workers ); return 0; }
int main (int argc, char *argv[]) { // curl_login("*****@*****.**","12345678"); // std::cout << response.str()<< "------------3-----------" << std::endl; // Prepare our context and socket zmq::context_t context (1); // zmq::socket_t socket (context, ZMQ_REP); // socket.bind ("tcp://*:5555"); int totalUsuarios = 5; zmq::socket_t clients (context, ZMQ_ROUTER); clients.bind ("tcp://*:5555"); zmq::socket_t workers (context, ZMQ_DEALER); workers.bind ("inproc://workers"); recursos_juego.manejador_juego = new Recursos(5); recursos_juego.contex = &context; for (int thread_nbr = 0; thread_nbr != 5; thread_nbr++) { pthread_t worker; pthread_create (&worker, NULL, worker_routine, (void *) &recursos_juego); } zmq::proxy (clients, workers, NULL); return 0; ////////////////////////////////////////////////////////////// // int count = 0; // std::cout << "Listen in port 5555" << std::endl; // while (true) { // zmq::message_t request; // // Espera por algún mensaje de los usuarios // socket.recv (&request); // // Conversión de message_t a string // std::string rpl = std::string(static_cast<char*>(request.data()), request.size()); // // std::cout << rpl << std::endl; // if(!readerJson.parse(rpl,mensajeCliente)) // Se verifica que se realice correctamente la conversion // { // std::cout << "Error en la conversión de documento Json a Objeto Json\n" // << readerJson.getFormattedErrorMessages(); // } // // idObjeto contiene la indentificación de qué objeto debemos tratar // tipoObjeto = mensajeCliente.get("idObjeto", "Not Found" ).asString(); // se obtiene el valor en la clave 'idObjeto' // data = mensajeCliente.get("data", "Not Found" ).asString(); // se obtiene el valor en la clave 'data' // if( tipoObjeto == "usuario"){ // Usuario user(&data); //Se crear el conjeto a partir del Json en formato String // std::cout << "Usuario "<< user.getNickName() << " conectado desde" << std::endl // << "Latitud: "<< user.getLatitud() << " Longitud: "<< user.getLongitud()<< std::endl; // }else if (tipoObjeto == "ataque"){ // }else if (tipoObjeto == "posUsuario"){ // }else if (tipoObjeto == "login"){ // }else{ // std::cout << "Json sin identificacion de Objeto "<< std::endl; // } // // Do some 'work' // // sleep(1); // //Responde al mensaje de los usuarios // std::stringstream lineStream(replyServer); // // Conversión de stringstreamer a zmq::message_t // zmq::message_t reply ((void*)lineStream.str().c_str(), lineStream.str().size()+1, NULL); // socket.send (reply); // count = count + 1; // } // return 0; }
int main(int argc, char * argv[]) { int NUMTHREADS=10; if (argc>1) NUMTHREADS=atoi(argv[1]); ImageProducer producer; Thread p1(std::ref(producer)); p1.detach(); Queue<Worker::value_type*> q(30); size_t stride = 4000; // shall match L1 cache __sync_lock_test_and_set(&Worker::start,NUMTHREADS+1); ThreadGroup threads; threads.reserve(NUMTHREADS); std::vector<Worker> workers(NUMTHREADS, Worker(q)); for (int i=0; i<NUMTHREADS; ++i) { threads.push_back(Thread(std::ref(workers[i]))); } // we shall wait for all threads to be ready... // (for timing) do{}while(Worker::start!=1); // start worker __sync_add_and_fetch(&Worker::start,-1); long long mapTime=0; long long reduceTime=0; for (int l=0; l<10;++l) { // reset queue; //q.reset(); if ( producer.q.empty() ) std::cout << "producer empty" << std::endl; if ( producer.q.full() ) std::cout << "producer full" << std::endl; ImageProducer::value_type * image; producer.q.pop(image); //map long long st = rdtsc(); ImageProducer::value_type * curr = image; ImageProducer::value_type * end = image+ ImageProducer::imageSize; while(curr<end) { // std::cout << curr-image << " " << (int)(*curr) << std::endl; q.push(curr); curr+=stride; } // barrier do{} while (!q.empty()); mapTime+= rdtsc()-st; // reduce std::vector<int> hist(256); st = rdtsc(); for (int i=0; i!=NUMTHREADS;++i) for (int j=0; j!=256;++j) hist[j]+= workers[i].hist[j]; reduceTime+= rdtsc()-st; for (int i=0; i!=NUMTHREADS;++i) { std::cout << "thread "<< i << " : "; for (int j=0; j!=256;++j) std::cout << workers[i].hist[j] << " ,"; std::cout << std::endl; } std::cout << "\nTotal " << l << std::endl; for (int j=0; j!=256;++j) std::cout << hist[j] << " ,"; std::cout << std::endl; delete [] image; // prepare new loop (actually part of reduce step) for (int i=0; i<NUMTHREADS; ++i) workers[i].zero(); } Worker::active=false; q.drain(); std::for_each(threads.begin(),threads.end(), std::bind(&Thread::join,std::placeholders::_1)); std::cout << "map time " << double(mapTime)/1000. << std::endl; std::cout << "reduce time " << double(reduceTime)/1000. << std::endl; return 0; }
int main(int argc, char** argv) { namespace po = boost::program_options; po::options_description desc("Options"); desc.add_options() ("help", "Print help messages") ("handystats-config", po::value<std::string>(), "Handystats configuration (in JSON format)" ) ("threads", po::value<uint64_t>(&threads)->default_value(threads), "Number of worker threads" ) ("step", po::value<std::vector<uint64_t>>(&steps)->multitoken()->required(), "Load step pairs (rate, seconds), e.g. --step 100 10 --step 200 10" ) ("timers", po::value<uint64_t>(&timers)->default_value(timers), "Number of different timers (0 for no timers)" ) ("counters", po::value<uint64_t>(&counters)->default_value(counters), "Number of different counters (0 for no counters)" ) ("gauges", po::value<uint64_t>(&gauges)->default_value(gauges), "Number of different gauges (0 for no gauges)" ) ("output-interval", po::value<uint64_t>()->default_value(output_interval.count()), "Stats output interval (in milliseconds)" ) ; po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, desc), vm); if (vm.count("help")) { std::cout << desc << std::endl; return 0; } po::notify(vm); } catch(po::error& e) { std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return 1; } if (vm["threads"].as<uint64_t>() == 0) { std::cerr << "ERROR: number of threads must be greater than 0" << std::endl; return 1; } if (!vm["timers"].as<uint64_t>() && !vm["counters"].as<uint64_t>() && !vm["gauges"].as<uint64_t>()) { std::cerr << "ERROR: at least one metric type must be specified (timers, counters, gauges)" << std::endl; return 1; } if (vm.count("handystats-config")) { HANDY_CONFIG_JSON(vm["handystats-config"].as<std::string>().c_str()); } output_interval = std::chrono::milliseconds(vm["output-interval"].as<uint64_t>()); HANDY_INIT(); std::atomic<bool> stop_flag(false); std::thread stats_printer( [&stop_flag] () { while (!stop_flag.load()) { const auto& start_time = handystats::chrono::tsc_clock::now(); print_stats(); const auto& end_time = handystats::chrono::tsc_clock::now(); const auto& call_time = handystats::chrono::duration::convert_to( handystats::chrono::time_unit::NSEC, end_time - start_time ); std::this_thread::sleep_for(output_interval - std::chrono::nanoseconds(call_time.count())); } } ); std::vector<std::thread> workers(threads); for (size_t step_index = 0; step_index < steps.size(); step_index += 2) { uint64_t step_rate = steps[step_index]; uint64_t step_time_limit = steps[step_index + 1]; if (step_time_limit == 0) { continue; } rate.store(step_rate); end_time.store( handystats::chrono::duration::convert_to(handystats::chrono::time_unit::USEC, ( handystats::chrono::tsc_clock::now() + handystats::chrono::duration(step_time_limit, handystats::chrono::time_unit::SEC) ).time_since_epoch() ).count() ); if (step_rate == 0) { std::this_thread::sleep_for(std::chrono::seconds(step_time_limit)); continue; } handystats::chrono::duration command_time_limit = handystats::chrono::duration::convert_to( handystats::chrono::time_unit::NSEC, handystats::chrono::duration(1, handystats::chrono::time_unit::SEC) ) * threads / step_rate; handystats::chrono::duration time_limit(step_time_limit, handystats::chrono::time_unit::SEC); for (auto& worker : workers) { worker = std::thread( [command_time_limit, time_limit] () { handystats::benchmarks::command_executor::run_for( [] () { command(); }, command_time_limit, time_limit ); } ); } for (auto& worker : workers) { worker.join(); } } stop_flag.store(true); stats_printer.join(); HANDY_FINALIZE(); }
int main(int argc, char** argv) { if(argc<2) { FATAL_ERROR("Not enough parameters"); } Queries queries = Queries::loadFromFile(std::string(argv[1])); const int numRuns = argc==2 ? 1 : std::stoi(std::string(argv[2])); size_t numThreads = std::thread::hardware_concurrency()/2; if(argc>3) { numThreads = std::stoi(std::string(argv[3])); } LOG_PRINT("[Main] Using "<< numThreads <<" threads"); size_t bfsLimit = std::numeric_limits<uint64_t>::max(); if(argc>4) { bfsLimit = std::stoi(std::string(argv[4])); LOG_PRINT("[Main] Limit to "<< bfsLimit <<" bfs"); } vector<std::unique_ptr<BFSBenchmark>> benchmarks; #ifdef AVX2 benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,1,true>>("Huge Batch BFS Runner 256 SP (width 1)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,1,false>>("Huge Batch BFS Runner 256 NoSP (width 1)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,2,true>>("Huge Batch BFS Runner 256 SP (width 2)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,2,false>>("Huge Batch BFS Runner 256 NoSp (width 2)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,4,true>>("Huge Batch BFS Runner 256 SP (width 4)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m256i,4,false>>("Huge Batch BFS Runner 256 NoSp (width 4)"))); // benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::BatchBFSRunner256>("Batch BFS Runner 256"))); #endif //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m128i,1>>("Huge Batch BFS Runner 128 (width 1)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint64_t,1>>("Huge Batch BFS Runner 64 (width 1)"))); benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<__m128i,4,false>>("Huge Batch BFS Runner 128 (width 4)"))); // benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint64_t,8>>("Huge Batch BFS Runner 64 (width 8)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint32_t,16>>("Huge Batch BFS Runner 32 (width 16)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint16_t,32>>("Huge Batch BFS Runner 16 (width 32)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint8_t,64>>("Huge Batch BFS Runner 8 (width 64)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint8_t,1>>("Huge Batch BFS Runner 8 (width 1)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::BatchBFSRunner128>("BatchBFSRunner128"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint64_t,2>>("Huge Batch BFS Runner 64 (width 2)"))); //benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::HugeBatchBfs<uint64_t,4>>("Huge Batch BFS Runner 64 (width 4)"))); // benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::BatchBFSRunner>("BatchBFSRunner64"))); // benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::NoQueueBFSRunner>("NoQueueBFSRunner"))); // benchmarks.push_back(std::unique_ptr<BFSBenchmark>(new SpecializedBFSBenchmark<Query4::BFSRunner>("BFSRunner"))); size_t maxBatchSize=0; for(auto& benchmark : benchmarks) { if(benchmark->batchSize()>maxBatchSize) { maxBatchSize = benchmark->batchSize(); } } LOG_PRINT("[Main] Max batch size: "<<maxBatchSize); // Allocate additional worker threads Workers workers(numThreads-1); // Run benchmarks uint32_t minAvgRuntime=std::numeric_limits<uint32_t>::max(); for(unsigned i=0; i<queries.queries.size(); i++) { Query query = queries.queries[i]; LOG_PRINT("[Main] Executing query "<<query.dataset); auto personGraph = Graph<Query4::PersonId>::loadFromPath(query.dataset); { auto ranges = generateTasks(bfsLimit, personGraph.size(), maxBatchSize); auto desiredTasks=numThreads*4; if(ranges.size()<desiredTasks) { FATAL_ERROR("[Main] Not enough tasks! #Threads="<<numThreads<<", #Tasks="<<ranges.size()<<", #DesiredTasks="<<desiredTasks); } } // XXX: Do one warmup run? for(const auto& b : benchmarks) { cout<<"# Benchmarking "<<b->name<<" ... "; cout.flush(); for(int a=0; a<numRuns; a++) { b->initTrace(personGraph.numVertices, personGraph.numEdges, numThreads, bfsLimit, "NotWorkingHere"); b->run(7, personGraph, query.reference, workers, bfsLimit); cout<<b->lastRuntime()<<"ms "; cout.flush(); } if(b->avgRuntime()<minAvgRuntime) { minAvgRuntime=b->avgRuntime(); cout<<" new best => "<<minAvgRuntime; } cout<<" ... avg: "<<b->avgRuntime()<<" rel: "<< b->avgRuntime()/(double)minAvgRuntime<<"x"<<endl; } } workers.close(); // Print final results for(const auto& b : benchmarks) { cout<<b->avgRuntime()<<"\t"<<(b->avgRuntime()/(double)minAvgRuntime)<<" # (ms, factor) "<<b->name<<endl; } return 0; }
void WorkerCrashLogger:: test() { // It should fetch information asynchronously of crashed workers. { DEBUG TaskInfo ti("Catch info from a previously crashed worker"); std::string name = "WorkerCrashLogger1"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); //for (int consume=0; consume<2; consume++) ISchedule::ptr schedule(new DummyScheduler); Bedroom::ptr bedroom(new Bedroom); Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom)))); { WorkerCrashLogger wcl(workers); } // Catch info from a previously crashed worker addAndWaitForStop(workers); addAndWaitForStop(workers); { TRACE_PERF("Init"); WorkerCrashLogger wcl(workers); a.processEvents (); // Init new thread before telling it to quit // When the thread quits. Wait for the beautifier to log everything. } // Should have consumed all workers Workers::DeadEngines de = workers.write ()->clean_dead_workers(); EXCEPTION_ASSERT_EQUALS(de.size (), 0u); } { DEBUG TaskInfo ti("Catch info from a crashed worker as it happens"); std::string name = "WorkerCrashLogger2"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); ISchedule::ptr schedule(new DummyScheduler); Bedroom::ptr bedroom(new Bedroom); Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom)))); { TRACE_PERF("Catch info from a crashed worker as it happens"); WorkerCrashLogger wcl(workers); // Catch info from a crashed worker as it happens addAndWaitForStop(workers); addAndWaitForStop(workers); } Workers::DeadEngines de = workers.write ()->clean_dead_workers(); EXCEPTION_ASSERT_EQUALS(de.size (), 0u); } { DEBUG TaskInfo ti("Support not consuming workers"); std::string name = "WorkerCrashLogger3"; int argc = 1; char * argv = &name[0]; QApplication a(argc,&argv); ISchedule::ptr schedule(new DummyScheduler); Bedroom::ptr bedroom(new Bedroom); Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom)))); // Catch info from a previously crashed worker addAndWaitForStop(workers); { TRACE_PERF("Support not consuming workers"); WorkerCrashLogger wcl(workers, false); a.processEvents (); // Catch info from a crashed worker as it happens addAndWaitForStop(workers); } // Should not have consumed any workers Workers::DeadEngines de = workers.write ()->clean_dead_workers(); EXCEPTION_ASSERT_EQUALS(de.size (), 2u); } }
int ChainInfo:: dead_workers() { auto workers = chain_.read ()->workers().read (); return workers->workers().size() - workers->n_workers(); }