Skip to content
Snippets Groups Projects
MpiUncertainty_exc.cc 8.39 KiB
Newer Older
  • Learn to ignore specific revisions
  • Radim Vavřík's avatar
    Radim Vavřík committed
    /**
     *       @file  MpiUncertainty_exc.cc
     *      @brief  The MpiUncertainty BarbequeRTRM application
     *
     * Description: to be done...
     *
     *     @author  Name Surname (nickname), your@email.com
     *
     *     Company  Your Company
     *   Copyright  Copyright (c) 20XX, Name Surname
     *
     * This source code is released for free distribution under the terms of the
     * GNU General Public License as published by the Free Software Foundation.
     * =====================================================================================
     */
    
    
    #include "MpiUncertainty_exc.h"
    
    #include <cstdio>
    #include <bbque/utils/utility.h>
    #include <bbque/monitors/operating_point.h>
    
    #include <unistd.h>
    #include <mpi.h>
     #include <omp.h>
    #include "MatData.h"
    #include "easylogging++.h"
    
    namespace ba = bbque::rtlib::as;
    extern ba::OperatingPointsList opList;
    extern ba::OperatingPointsList opList2;
    
    #define _ELPP_THREAD_SAFE
    
    _INITIALIZE_EASYLOGGINGPP
    
    MpiUncertainty::MpiUncertainty(std::string const & name,
    		std::string const & uncertaintyConfigXmlPath,
    		std::string const & recipe,
    		RTLIB_Services_t *rtlib) :
    	BbqueEXC(name, recipe, rtlib),
    	m_configXmlPath(uncertaintyConfigXmlPath) {
    
    	logger->Warn("New MpiUncertainty::MpiUncertainty()");
    
    	// NOTE: since RTLib 1.1 the derived class construct should be used
    	// mainly to specify instantiation parameters. All resource
    	// acquisition, especially threads creation, should be palced into the
    	// new onSetup() method.
    
    	logger->Info("EXC Unique IDentifier (UID): %u", GetUid());
    
    }
    
    RTLIB_ExitCode_t MpiUncertainty::onSetup() {
    	// This is just an empty method in the current implementation of this
    	// testing application. However, this is intended to collect all the
    	// application specific initialization code, especially the code which
    	// acquire system resources (e.g. thread creation)
    	logger->Warn("MpiUncertainty::onSetup()");
    
    	// UNCERTAINTY LOGGER SETTINGS ////////////////////////////////////////////////////////////////
    	/* Init logger */
    	//_START_EASYLOGGINGPP();
    
    	/* Logger configuration */
    	// Change default format
    	el::Configurations defaultConf;
       	defaultConf.setToDefault();
       	defaultConf.setGlobally(el::ConfigurationType::Format, "%level [%logger] %msg");
       	//defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%level [%logger]  %msg");
       	el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
    
    	el::Loggers::reconfigureLogger("default", defaultConf);
       	
    	// Register logger for model
    	el::Loggers::getLogger("model");
       	el::Loggers::reconfigureLogger("model", defaultConf);
    
       	// Register logger for montecarlo
    	el::Loggers::getLogger("montecarlo");
    	el::Loggers::reconfigureLogger("montecarlo", defaultConf);
    
    	// Load configuration for QoS modes and logger
    	pugi::xml_document doc;
    	pugi::xml_parse_result result = doc.load_file(m_configXmlPath.c_str());
    	if (result.status != pugi::status_ok)
    	{
    		// Config file load unsuccesfull
    		LOG(FATAL) << "Configuration load result: " << std::string(result.description());
    		std::exit(EXIT_FAILURE);
    	} 
    	else
    	{
    		// Initialize values for QoS modes
    		m_jobsNumber[0] = doc.child("conf").child("uncertainity").child("params").child("mcCount").text().as_int();
    		m_timeFrame[0] = doc.child("conf").child("uncertainity").child("params").child("timeframe").text().as_int();
    		m_jobsNumber[1] = doc.child("conf").child("uncertainity").child("params").child("mcCount1").text().as_int();
    		m_timeFrame[1] = doc.child("conf").child("uncertainity").child("params").child("timeframe1").text().as_int();
    		m_jobsNumber[2] = doc.child("conf").child("uncertainity").child("params").child("mcCount2").text().as_int();
    		m_timeFrame[2] = doc.child("conf").child("uncertainity").child("params").child("timeframe2").text().as_int();
    		m_jobsNumber[3] = doc.child("conf").child("uncertainity").child("params").child("mcCount3").text().as_int();
    		m_timeFrame[3] = doc.child("conf").child("uncertainity").child("params").child("timeframe3").text().as_int();
    
    		// Set loglevel
    		std::string loglevel = doc.child("conf").child("math1D").child("logLevel").text().as_string();
    		#ifdef DEBUG
    			el::Loggers::setLoggingLevel(el::Level::Debug);
    		#else
    			if(loglevel == "DEBUG") el::Loggers::setLoggingLevel(el::Level::Debug);
    			else if(loglevel == "INFO") el::Loggers::setLoggingLevel(el::Level::Info);
    			else if(loglevel == "WARNING") el::Loggers::setLoggingLevel(el::Level::Warning);
    			else if(loglevel == "ERROR") el::Loggers::setLoggingLevel(el::Level::Error);
    			else LOG(WARNING) << "Unknown logging level " << loglevel << " selected!";
    		#endif
    	}
    	/////////////////////////////////////////////////////////////////////////////////////////////////
       	
    	LOG(INFO) << "Math1D Model";
    
       	/* MPI Initialize */
    	MPI::Init();//argc, argv);
    
    	if(MPI::Is_initialized())
    	{
    		logger->Info("MPI Initialized");
    	} else {
    		logger->Warn("MPI was not initialized");
    		std::exit(-1);		
    	}
    
    	int rank = -1, numProc = -1; // Holds rank of current process and total number of processes
    	MPI_Comm_size(MPI_COMM_WORLD, &numProc);
    	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
    	// Do the first run of the model
    	std::shared_ptr<math1d_cl::MatData> matData = std::make_shared<math1d_cl::MatData>(m_configXmlPath);
    	matData->runRR();
    
    	// Check FWL within simulated values in measured stations and select QoS mode according current situation (FWL)
    	m_qosMode = matData->checkFWL();
    	logger->Warn("QoS mode %d selected (%d MC samples, %d sec)", m_qosMode, m_jobsNumber[m_qosMode], m_timeFrame[m_qosMode]);
    
    	// Start timer
    	m_timer.start();
    
    	// // REMOVE
    	// MPI_Barrier(MPI_COMM_WORLD);
    	
    	// Generate samples
    	m_uncertainty = std::unique_ptr<math1d_cl::Uncertainity>(new math1d_cl::Uncertainity(m_configXmlPath, matData, m_jobsNumber[m_qosMode]));
    
    	m_uncertainty->Initialize();
    
    	return RTLIB_OK;
    }
    
    RTLIB_ExitCode_t MpiUncertainty::onConfigure(uint8_t awm_id) {
    
    	logger->Warn("MpiUncertainty::onConfigure(): EXC [%s] => AWM [%02d]",
    		exc_name.c_str(), awm_id);
    
    	// Extracting parameters
    	if(rpc_name == "MpiUncertainty")
    		m_threadsNumber = opList[awm_id].parameters["threads"];
    	else if(rpc_name == "MpiUncertainty2")
    		m_threadsNumber = opList2[awm_id].parameters["threads"];
    	// add more recipes and oplists
    
    	m_uncertainty->CreateModels(m_threadsNumber);
    
    	logger->Warn("[onConfigure]: Configured with <threads>: <%d> via %s recipe",
    		m_threadsNumber, rpc_name.c_str());
    
    	return RTLIB_OK;
    }
    
    RTLIB_ExitCode_t MpiUncertainty::onRun() {
    	RTLIB_WorkingModeParams_t const wmp = WorkingModeParams();
    
    	// Return after all jobs done
    	if(m_jobsDone >= m_jobsNumber[m_qosMode])
    		return RTLIB_EXC_WORKLOAD_NONE;
    
    	// Do one more cycle
    	logger->Warn("MpiUncertainty::onRun()      : EXC [%s]  @ AWM [%02d]",
    		exc_name.c_str(), wmp.awm_id);
    
    	// Set number of OMP threads to uncertainty and simulate given chunk of MC samples
    	m_uncertainty->RunMC(m_threadsNumber);
    
    	m_jobsDone += m_threadsNumber;
    
    	logger->Warn("%d Monte Carlo samples computed, %d out of %d in total", m_threadsNumber, m_jobsDone, m_jobsNumber[m_qosMode]);
    
    	// Compute the average time required to simulate one MC sample	
    	m_avgTimePerSimulation = m_timer.getElapsedTimeMs() / m_jobsDone;
    
    	// or ???
    	// m_avgTimePerSimulation = timePerOnRun / m_tthreadsNumber;
    
    	return RTLIB_OK;
    }
    
    RTLIB_ExitCode_t MpiUncertainty::onMonitor() {
    	RTLIB_WorkingModeParams_t const wmp = WorkingModeParams();
    
    	logger->Warn("MpiUncertainty::onMonitor()  : EXC [%s]  @ AWM [%02d], Cycle [%4d]",
    		exc_name.c_str(), wmp.awm_id, Cycles());
    
    	// Compute time required to simulate the remaining number of MC samples at a current speed
    	double timeRequired = (m_jobsNumber[m_qosMode] - m_jobsDone) * m_avgTimePerSimulation;
    
    	double estimatedTotalTime = timeRequired + m_timer.getElapsedTimeMs();
    
    	// If this remaining time plus the actual total execution time exceeds the time slot limit
    	// defined by the QoS mode, the higher AWM is requested
    	if((estimatedTotalTime) > m_timeFrame[m_qosMode] * 1000.0)
    	{
    		int goalGap = (1 - (estimatedTotalTime / timeRequired - 1)) * 100;
    		logger->Warn("MpiUncertainty::onMonitor()  : Requesting higher AWM, gap is %d", goalGap);
    		SetGoalGap(goalGap);
    	} else
    		logger->Warn("MpiUncertainty::onMonitor()  : Current AWM is OK");
    
    	// Exploit less threads if less jobs remain
    	if ( m_jobsNumber[m_qosMode] - m_jobsDone < m_threadsNumber )
    		m_threadsNumber = m_jobsNumber[m_qosMode] - m_jobsDone;
    
    	return RTLIB_OK;
    }
    
    RTLIB_ExitCode_t MpiUncertainty::onRelease() {
    	// Collect results
    	m_uncertainty->CollectResults();
    
    	logger->Warn("MpiUncertainty::onRelease()  : exit");
    
    	return RTLIB_OK;
    }