Dynare parallel: preprocessor implementation
parent
9ebcecb266
commit
c28d15d78a
|
@ -0,0 +1,482 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Dynare Team
|
||||||
|
*
|
||||||
|
* This file is part of Dynare.
|
||||||
|
*
|
||||||
|
* Dynare is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Dynare is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ConfigFile.hh"
|
||||||
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
SlaveNode::SlaveNode(string &computerName_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
|
||||||
|
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
|
||||||
|
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg) :
|
||||||
|
computerName(computerName_arg), minCpuNbr(minCpuNbr_arg), maxCpuNbr(maxCpuNbr_arg), userName(userName_arg),
|
||||||
|
password(password_arg), remoteDrive(remoteDrive_arg), remoteDirectory(remoteDirectory_arg), dynarePath(dynarePath_arg),
|
||||||
|
matlabOctavePath(matlabOctavePath_arg), singleCompThread(singleCompThread_arg)
|
||||||
|
{
|
||||||
|
if (computerName.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: The node must have a ComputerName." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Cluster::Cluster(vector<string> member_nodes_arg) : member_nodes(member_nodes_arg)
|
||||||
|
{
|
||||||
|
if (member_nodes.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: The cluster must have at least one member node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigFile::ConfigFile(bool parallel_arg, bool parallel_test_arg,
|
||||||
|
bool parallel_slave_open_mode_arg, const string &cluster_name_arg) :
|
||||||
|
parallel(parallel_arg), parallel_test(parallel_test_arg),
|
||||||
|
parallel_slave_open_mode(parallel_slave_open_mode_arg), cluster_name(cluster_name_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigFile::~ConfigFile()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::getConfigFileInfo(const string ¶llel_config_file)
|
||||||
|
{
|
||||||
|
if (!parallel && !parallel_test)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ifstream *configFile;
|
||||||
|
if (parallel_config_file.empty())
|
||||||
|
{
|
||||||
|
// Test OS and try to open default file
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
|
string defaultConfigFile (getenv("APPDATA"));
|
||||||
|
if (&defaultConfigFile==NULL)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: APPDATA environment variable not found." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
defaultConfigFile += "\\dynare.ini";
|
||||||
|
#else
|
||||||
|
string defaultConfigFile (getenv("HOME"));
|
||||||
|
if (&defaultConfigFile==NULL)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: HOME environment variable not found." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
defaultConfigFile += "/.dynare";
|
||||||
|
#endif
|
||||||
|
configFile = new ifstream(defaultConfigFile.c_str(), fstream::in);
|
||||||
|
if (!configFile->is_open())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Could not open the default config file" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configFile = new ifstream(parallel_config_file.c_str(), fstream::in);
|
||||||
|
if (!configFile->is_open())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Couldn't open file " << parallel_config_file << endl;;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string name, computerName, userName, password, remoteDrive,
|
||||||
|
remoteDirectory, dynarePath, matlabOctavePath;
|
||||||
|
int minCpuNbr = 0, maxCpuNbr = 0;
|
||||||
|
bool singleCompThread = true;
|
||||||
|
vector<string> member_nodes;
|
||||||
|
|
||||||
|
bool inNode = false;
|
||||||
|
bool inCluster = false;
|
||||||
|
while (configFile->good())
|
||||||
|
{
|
||||||
|
string line;
|
||||||
|
getline(*configFile, line);
|
||||||
|
boost::trim(line);
|
||||||
|
if (line.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!line.compare("[node]") || !line.compare("[cluster]"))
|
||||||
|
{
|
||||||
|
addConfFileElement(inNode, inCluster, member_nodes, name,
|
||||||
|
computerName, minCpuNbr, maxCpuNbr, userName,
|
||||||
|
password, remoteDrive, remoteDirectory,
|
||||||
|
dynarePath, matlabOctavePath, singleCompThread);
|
||||||
|
|
||||||
|
//! Reset communication vars / option defaults
|
||||||
|
if (!line.compare("[node]"))
|
||||||
|
{
|
||||||
|
inNode = true;
|
||||||
|
inCluster = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inNode = false;
|
||||||
|
inCluster = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = userName = computerName = password = remoteDrive =
|
||||||
|
remoteDirectory = dynarePath = matlabOctavePath = "";
|
||||||
|
minCpuNbr = maxCpuNbr = 0;
|
||||||
|
singleCompThread = true;
|
||||||
|
member_nodes.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector<string> tokenizedLine;
|
||||||
|
boost::split(tokenizedLine, line, boost::is_any_of("="));
|
||||||
|
if (tokenizedLine.size() != 2)
|
||||||
|
{
|
||||||
|
cerr << "ERROR (in config file): Options should be formatted as 'option = value'." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
boost::trim(tokenizedLine.front());
|
||||||
|
boost::trim(tokenizedLine.back());
|
||||||
|
|
||||||
|
if (!tokenizedLine.front().compare("Name"))
|
||||||
|
name = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("CPUnbr"))
|
||||||
|
{
|
||||||
|
vector<string> tokenizedCpuNbr;
|
||||||
|
boost::split(tokenizedCpuNbr, tokenizedLine.back(), boost::is_any_of(":"));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (tokenizedCpuNbr.size() == 1)
|
||||||
|
{
|
||||||
|
minCpuNbr = 1;
|
||||||
|
maxCpuNbr = boost::lexical_cast< int >(tokenizedCpuNbr.front());
|
||||||
|
}
|
||||||
|
else if (tokenizedCpuNbr.size() == 2 &&
|
||||||
|
tokenizedCpuNbr[0].at(0) == '[' &&
|
||||||
|
tokenizedCpuNbr[1].at(tokenizedCpuNbr[1].size()-1) == ']')
|
||||||
|
{
|
||||||
|
tokenizedCpuNbr[0].erase(0,1);
|
||||||
|
tokenizedCpuNbr[1].erase(tokenizedCpuNbr[1].size()-1,1);
|
||||||
|
minCpuNbr = boost::lexical_cast< int >(tokenizedCpuNbr[0]);
|
||||||
|
maxCpuNbr = boost::lexical_cast< int >(tokenizedCpuNbr[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( const boost::bad_lexical_cast & )
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Could not convert value to integer for CPUnbr." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minCpuNbr <= 0 || maxCpuNbr <= 0)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Syntax for the CPUnbr option is as follows:" << endl
|
||||||
|
<< " 1) CPUnbr = <int>" << endl
|
||||||
|
<< " or 2) CPUnbr = [<int>:<int>]" << endl
|
||||||
|
<< " where <int> is an Integer > 0." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
minCpuNbr--;
|
||||||
|
maxCpuNbr--;
|
||||||
|
if (minCpuNbr > maxCpuNbr)
|
||||||
|
{
|
||||||
|
int tmp = maxCpuNbr;
|
||||||
|
maxCpuNbr = minCpuNbr;
|
||||||
|
minCpuNbr = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!tokenizedLine.front().compare("ComputerName"))
|
||||||
|
computerName = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("UserName"))
|
||||||
|
userName = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("Password"))
|
||||||
|
password = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("RemoteDrive"))
|
||||||
|
remoteDrive = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("RemoteDirectory"))
|
||||||
|
remoteDirectory = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("DynarePath"))
|
||||||
|
dynarePath = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("MatlabOctavePath"))
|
||||||
|
matlabOctavePath = tokenizedLine.back();
|
||||||
|
else if (!tokenizedLine.front().compare("SingleCompThread"))
|
||||||
|
if (tokenizedLine.back().compare("true"))
|
||||||
|
singleCompThread = true;
|
||||||
|
else if (tokenizedLine.back().compare("false"))
|
||||||
|
singleCompThread = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "ERROR (in config file): The value passed to SingleCompThread may only be 'true' or 'false'." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else if (!tokenizedLine.front().compare("Members"))
|
||||||
|
{
|
||||||
|
vector<string> tmp_member_nodes;
|
||||||
|
boost::split(tmp_member_nodes, tokenizedLine.back(), boost::is_any_of(";, "));
|
||||||
|
for ( vector<string>::iterator it = tmp_member_nodes.begin();
|
||||||
|
it < tmp_member_nodes.end(); it++ )
|
||||||
|
{
|
||||||
|
boost::trim(*it);
|
||||||
|
if (!it->empty())
|
||||||
|
member_nodes.push_back(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "ERROR (in config file): Option " << tokenizedLine.front() << " is invalid." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addConfFileElement(inNode, inCluster, member_nodes, name,
|
||||||
|
computerName, minCpuNbr, maxCpuNbr, userName,
|
||||||
|
password, remoteDrive, remoteDirectory,
|
||||||
|
dynarePath, matlabOctavePath, singleCompThread);
|
||||||
|
configFile->close();
|
||||||
|
delete configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::addConfFileElement(bool inNode, bool inCluster, vector<string> member_nodes, string &name,
|
||||||
|
string &computerName, int minCpuNbr, int maxCpuNbr, string &userName,
|
||||||
|
string &password, string &remoteDrive, string &remoteDirectory,
|
||||||
|
string &dynarePath, string &matlabOctavePath, bool singleCompThread)
|
||||||
|
{
|
||||||
|
//! ADD NODE
|
||||||
|
if (inNode)
|
||||||
|
if (!member_nodes.empty())
|
||||||
|
{
|
||||||
|
cerr << "Invalid option passed to [node]." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (name.empty() || slave_nodes.find(name) != slave_nodes.end())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Every node must be assigned a unique name." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
slave_nodes[name] = new SlaveNode(computerName, minCpuNbr, maxCpuNbr, userName,
|
||||||
|
password, remoteDrive, remoteDirectory, dynarePath,
|
||||||
|
matlabOctavePath, singleCompThread);
|
||||||
|
//! ADD CLUSTER
|
||||||
|
else if (inCluster)
|
||||||
|
if ( minCpuNbr > 0 || maxCpuNbr > 0 || !userName.empty() ||
|
||||||
|
!password.empty() || !remoteDrive.empty() || !remoteDirectory.empty() ||
|
||||||
|
!dynarePath.empty() || !matlabOctavePath.empty())
|
||||||
|
{
|
||||||
|
cerr << "Invalid option passed to [cluster]." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (name.empty() || clusters.find(name) != clusters.end())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: The cluster must be assigned a unique name." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clusters.empty())
|
||||||
|
firstClusterName = name;
|
||||||
|
clusters[name] = new Cluster(member_nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::checkPass() const
|
||||||
|
{
|
||||||
|
if (!parallel && !parallel_test)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//! Check Slave Nodes
|
||||||
|
if (slave_nodes.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: At least one node must be defined in the config file." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||||
|
it != slave_nodes.end(); it++)
|
||||||
|
{
|
||||||
|
#if !defined(_WIN32) && !defined(__CYGWIN32__)
|
||||||
|
//For Linux/Mac, check that cpuNbr starts at 0
|
||||||
|
if (it->second->minCpuNbr != 0)
|
||||||
|
cout << "WARNING: On Unix-based operating systems, you cannot specify the CPU that is used "
|
||||||
|
<< "in parallel processing. This will be adjusted for you such that the same number of CPUs "
|
||||||
|
<< "are used." << endl;
|
||||||
|
#endif
|
||||||
|
if (!it->second->computerName.compare("localhost")) // We are working locally
|
||||||
|
{
|
||||||
|
if (!it->second->remoteDrive.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the RemoteDrive option may not be passed for a local node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!it->second->remoteDirectory.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the RemoteDirectory option may not be passed for a local node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (it->second->userName.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the UserName option must be passed for every remote node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
|
if (it->second->userName.empty() || it->second->password.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the Password option must be passed under Windows for every remote node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (it->second->remoteDrive.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the RemoteDrive option must be passed under Windows for every remote node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (it->second->remoteDirectory.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR (node " << it->first << "): the RemoteDirectory must be specified for every remote node." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Check Clusters
|
||||||
|
if (clusters.empty())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: At least one cluster must be defined in the config file." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cluster_name.empty() && clusters.find(cluster_name) == clusters.end())
|
||||||
|
{
|
||||||
|
cerr << "ERROR: Cluster Name " << cluster_name << " was not found in the config file." << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (map<string, Cluster *>::const_iterator it = clusters.begin();
|
||||||
|
it != clusters.end(); it++)
|
||||||
|
for (vector<string>::const_iterator itmn = it->second->member_nodes.begin();
|
||||||
|
itmn < it->second->member_nodes.end(); itmn++)
|
||||||
|
if (slave_nodes.find(*itmn) == slave_nodes.end())
|
||||||
|
{
|
||||||
|
cerr << "Error: node " << *itmn << " specified in cluster " << it->first << " was not found" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::transformPass()
|
||||||
|
{
|
||||||
|
if (!parallel && !parallel_test)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if !defined(_WIN32) && !defined(__CYGWIN32__)
|
||||||
|
//For Linux/Mac, check that cpuNbr starts at 0
|
||||||
|
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||||
|
it != slave_nodes.end(); it++)
|
||||||
|
if (it->second->minCpuNbr != 0)
|
||||||
|
{
|
||||||
|
it->second->maxCpuNbr = it->second->maxCpuNbr - it->second->minCpuNbr;
|
||||||
|
it->second->minCpuNbr = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::writeCluster(ostream &output) const
|
||||||
|
{
|
||||||
|
if (!parallel && !parallel_test)
|
||||||
|
return;
|
||||||
|
|
||||||
|
map<string, Cluster *>::const_iterator cluster_it ;
|
||||||
|
if (cluster_name.empty())
|
||||||
|
cluster_it = clusters.find(firstClusterName);
|
||||||
|
else
|
||||||
|
cluster_it = clusters.find(cluster_name);
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
for (map<string, SlaveNode *>::const_iterator it = slave_nodes.begin();
|
||||||
|
it != slave_nodes.end(); it++)
|
||||||
|
{
|
||||||
|
bool slave_node_in_member_nodes = false;
|
||||||
|
for (vector<string>::const_iterator itmn = cluster_it->second->member_nodes.begin();
|
||||||
|
itmn < cluster_it->second->member_nodes.end(); itmn++)
|
||||||
|
if (!it->first.compare(*itmn))
|
||||||
|
slave_node_in_member_nodes = true;
|
||||||
|
|
||||||
|
if (!slave_node_in_member_nodes)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
output << "options_.parallel";
|
||||||
|
if (i > 1)
|
||||||
|
output << "(" << i << ")";
|
||||||
|
i++;
|
||||||
|
output << " = struct('Local', ";
|
||||||
|
if (it->second->computerName.compare("localhost"))
|
||||||
|
output << "0, ";
|
||||||
|
else
|
||||||
|
output << "1, ";
|
||||||
|
|
||||||
|
output << "'ComputerName', '" << it->second->computerName << "', "
|
||||||
|
<< "'CPUnbr', [" << it->second->minCpuNbr << ":" << it->second->maxCpuNbr << "], "
|
||||||
|
<< "'UserName', '" << it->second->userName << "', "
|
||||||
|
<< "'Password', '" << it->second->password << "', "
|
||||||
|
<< "'RemoteDrive', '" << it->second->remoteDrive << "', "
|
||||||
|
<< "'RemoteDirectory', '" << it->second->remoteDirectory << "', "
|
||||||
|
<< "'DynarePath', '" << it->second->dynarePath << "', "
|
||||||
|
<< "'MatlabOctavePath', '" << it->second->matlabOctavePath << "', ";
|
||||||
|
|
||||||
|
if (it->second->singleCompThread)
|
||||||
|
output << "'SingleCompThread', 'true');" << endl;
|
||||||
|
else
|
||||||
|
output << "'SingleCompThread', 'false');" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parallel_slave_open_mode)
|
||||||
|
output << "options_.parallel_info.leaveSlaveOpen = 1;" << endl;
|
||||||
|
|
||||||
|
output << "InitializeComputationalEnvironment();" << endl;
|
||||||
|
if (parallel_test)
|
||||||
|
output << "ErrorCode = AnalyseComputationalEnvironment(options_.parallel, options_.parallel_info);" << endl
|
||||||
|
<< "disp(['AnalyseComputationalEnvironment returned with Error Code: ' num2str(ErrorCode)]);" << endl
|
||||||
|
<< "diary off;" << endl
|
||||||
|
<< "return;" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigFile::writeEndParallel(ostream &output) const
|
||||||
|
{
|
||||||
|
if ((!parallel && !parallel_test) || !parallel_slave_open_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
output << "if options_.parallel_info.leaveSlaveOpen == 1" << endl
|
||||||
|
<< " closeSlave(options_.parallel,options_.parallel_info.RemoteTmpFolder);" << endl
|
||||||
|
<< "end" << endl;
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Dynare Team
|
||||||
|
*
|
||||||
|
* This file is part of Dynare.
|
||||||
|
*
|
||||||
|
* Dynare is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Dynare is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CONFIG_FILE_HH
|
||||||
|
#define _CONFIG_FILE_HH
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class SlaveNode
|
||||||
|
{
|
||||||
|
friend class ConfigFile;
|
||||||
|
public:
|
||||||
|
SlaveNode(string &computerName_arg, int minCpuNbr_arg, int maxCpuNbr_arg, string &userName_arg,
|
||||||
|
string &password_arg, string &remoteDrive_arg, string &remoteDirectory_arg,
|
||||||
|
string &dynarePath_arg, string &matlabOctavePath_arg, bool singleCompThread_arg);
|
||||||
|
~SlaveNode();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const string computerName;
|
||||||
|
int minCpuNbr;
|
||||||
|
int maxCpuNbr;
|
||||||
|
const string userName;
|
||||||
|
const string password;
|
||||||
|
const string remoteDrive;
|
||||||
|
const string remoteDirectory;
|
||||||
|
const string dynarePath;
|
||||||
|
const string matlabOctavePath;
|
||||||
|
const bool singleCompThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Cluster
|
||||||
|
{
|
||||||
|
friend class ConfigFile;
|
||||||
|
public:
|
||||||
|
Cluster(vector<string> member_nodes_arg);
|
||||||
|
~Cluster();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const vector<string> member_nodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! The abstract representation of a "config" file
|
||||||
|
class ConfigFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ConfigFile(bool parallel_arg, bool parallel_test_arg, bool parallel_slave_open_mode_arg, const string &cluster_name);
|
||||||
|
~ConfigFile();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool parallel;
|
||||||
|
const bool parallel_test;
|
||||||
|
const bool parallel_slave_open_mode;
|
||||||
|
const string cluster_name;
|
||||||
|
string firstClusterName;
|
||||||
|
//! Cluster Table
|
||||||
|
map<string, Cluster *> clusters;
|
||||||
|
//! Node Map
|
||||||
|
map<string, SlaveNode *> slave_nodes;
|
||||||
|
//! Add a SlaveNode or a Cluster object
|
||||||
|
void addConfFileElement(bool inNode, bool inCluster, vector<string> member_nodes, string &name,
|
||||||
|
string &computerName, int minCpuNbr, int maxCpuNbr, string &userName,
|
||||||
|
string &password, string &remoteDrive, string &remoteDirectory,
|
||||||
|
string &dynarePath, string &matlabOctavePath, bool singleCompThread);
|
||||||
|
public:
|
||||||
|
//! Parse config file
|
||||||
|
void getConfigFileInfo(const string ¶llel_config_file);
|
||||||
|
//! Check Pass
|
||||||
|
void checkPass() const;
|
||||||
|
//! Check Pass
|
||||||
|
void transformPass();
|
||||||
|
//! Create options_.parallel structure, write options
|
||||||
|
void writeCluster(ostream &output) const;
|
||||||
|
//! Close slave nodes if needed
|
||||||
|
void writeEndParallel(ostream &output) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ! CONFIG_FILE_HH
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2009 Dynare Team
|
* Copyright (C) 2003-2010 Dynare Team
|
||||||
*
|
*
|
||||||
* This file is part of Dynare.
|
* This file is part of Dynare.
|
||||||
*
|
*
|
||||||
|
@ -34,7 +34,9 @@ using namespace std;
|
||||||
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
|
Splitting main() in two parts was necessary because ParsingDriver.h and MacroDriver.h can't be
|
||||||
included simultaneously (because of Bison limitations).
|
included simultaneously (because of Bison limitations).
|
||||||
*/
|
*/
|
||||||
void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit
|
void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit,
|
||||||
|
bool parallel, const string ¶llel_config_file, const string &cluster_name, bool parallel_slave_open_mode,
|
||||||
|
bool parallel_test
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, bool cygwin, bool msvc
|
, bool cygwin, bool msvc
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,6 +46,7 @@ void
|
||||||
usage()
|
usage()
|
||||||
{
|
{
|
||||||
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [warn_uninit]"
|
cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [warn_uninit]"
|
||||||
|
<< " [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
<< " [cygwin] [msvc]"
|
<< " [cygwin] [msvc]"
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,6 +75,11 @@ main(int argc, char **argv)
|
||||||
bool cygwin = false;
|
bool cygwin = false;
|
||||||
bool msvc = false;
|
bool msvc = false;
|
||||||
#endif
|
#endif
|
||||||
|
string parallel_config_file;
|
||||||
|
bool parallel = false;
|
||||||
|
string cluster_name;
|
||||||
|
bool parallel_slave_open_mode = false;
|
||||||
|
bool parallel_test = false;
|
||||||
|
|
||||||
// Parse options
|
// Parse options
|
||||||
for (int arg = 2; arg < argc; arg++)
|
for (int arg = 2; arg < argc; arg++)
|
||||||
|
@ -107,6 +115,32 @@ main(int argc, char **argv)
|
||||||
else if (!strcmp(argv[arg], "msvc"))
|
else if (!strcmp(argv[arg], "msvc"))
|
||||||
msvc = true;
|
msvc = true;
|
||||||
#endif
|
#endif
|
||||||
|
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "conffile", 8))
|
||||||
|
{
|
||||||
|
if (strlen(argv[arg]) <= 9 || argv[arg][8] != '=')
|
||||||
|
{
|
||||||
|
cerr << "Incorrect syntax for conffile option" << endl;
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
parallel_config_file = string(argv[arg] + 9);
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[arg], "parallel_slave_open_mode"))
|
||||||
|
parallel_slave_open_mode = true;
|
||||||
|
else if (!strcmp(argv[arg], "parallel_test"))
|
||||||
|
parallel_test = true;
|
||||||
|
else if (strlen(argv[arg]) >= 8 && !strncmp(argv[arg], "parallel", 8))
|
||||||
|
{
|
||||||
|
parallel = true;
|
||||||
|
if (strlen(argv[arg]) > 8)
|
||||||
|
{
|
||||||
|
if (strlen(argv[arg]) == 9 || argv[arg][8] != '=')
|
||||||
|
{
|
||||||
|
cerr << "Incorrect syntax for parallel option" << endl;
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
cluster_name = string(argv[arg] + 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cerr << "Unknown option: " << argv[arg] << endl;
|
cerr << "Unknown option: " << argv[arg] << endl;
|
||||||
|
@ -146,7 +180,8 @@ main(int argc, char **argv)
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
// Do the rest
|
// Do the rest
|
||||||
main2(macro_output, basename, debug, clear_all, no_tmp_terms, warn_uninit
|
main2(macro_output, basename, debug, clear_all, no_tmp_terms, warn_uninit,
|
||||||
|
parallel, parallel_config_file, cluster_name, parallel_slave_open_mode, parallel_test
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, cygwin, msvc
|
, cygwin, msvc
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2008 Dynare Team
|
* Copyright (C) 2008-2010 Dynare Team
|
||||||
*
|
*
|
||||||
* This file is part of Dynare.
|
* This file is part of Dynare.
|
||||||
*
|
*
|
||||||
|
@ -23,9 +23,12 @@ using namespace std;
|
||||||
|
|
||||||
#include "ParsingDriver.hh"
|
#include "ParsingDriver.hh"
|
||||||
#include "ModFile.hh"
|
#include "ModFile.hh"
|
||||||
|
#include "ConfigFile.hh"
|
||||||
|
|
||||||
void
|
void
|
||||||
main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit
|
main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tmp_terms, bool warn_uninit,
|
||||||
|
bool parallel, const string ¶llel_config_file, const string &cluster_name, bool parallel_slave_open_mode,
|
||||||
|
bool parallel_test
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, bool cygwin, bool msvc
|
, bool cygwin, bool msvc
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,12 +38,16 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tm
|
||||||
|
|
||||||
// Do parsing and construct internal representation of mod file
|
// Do parsing and construct internal representation of mod file
|
||||||
ModFile *mod_file = p.parse(in, debug);
|
ModFile *mod_file = p.parse(in, debug);
|
||||||
|
ConfigFile config_file (parallel, parallel_test, parallel_slave_open_mode, cluster_name);
|
||||||
|
config_file.getConfigFileInfo(parallel_config_file);
|
||||||
|
|
||||||
// Run checking pass
|
// Run checking pass
|
||||||
mod_file->checkPass();
|
mod_file->checkPass();
|
||||||
|
config_file.checkPass();
|
||||||
|
|
||||||
// Perform transformations on the model (creation of auxiliary vars and equations)
|
// Perform transformations on the model (creation of auxiliary vars and equations)
|
||||||
mod_file->transformPass();
|
mod_file->transformPass();
|
||||||
|
config_file.transformPass();
|
||||||
|
|
||||||
// Evaluate parameters initialization, initval, endval and pounds
|
// Evaluate parameters initialization, initval, endval and pounds
|
||||||
mod_file->evalAllExpressions(warn_uninit);
|
mod_file->evalAllExpressions(warn_uninit);
|
||||||
|
@ -49,7 +56,7 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tm
|
||||||
mod_file->computingPass(no_tmp_terms);
|
mod_file->computingPass(no_tmp_terms);
|
||||||
|
|
||||||
// Write outputs
|
// Write outputs
|
||||||
mod_file->writeOutputFiles(basename, clear_all
|
mod_file->writeOutputFiles(basename, clear_all, config_file
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, cygwin, msvc
|
, cygwin, msvc
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,8 @@ dynare_m_SOURCES = \
|
||||||
DataTree.hh \
|
DataTree.hh \
|
||||||
ModFile.cc \
|
ModFile.cc \
|
||||||
ModFile.hh \
|
ModFile.hh \
|
||||||
|
ConfigFile.cc \
|
||||||
|
ConfigFile.hh \
|
||||||
Statement.cc \
|
Statement.cc \
|
||||||
Statement.hh \
|
Statement.hh \
|
||||||
ExprNode.cc \
|
ExprNode.cc \
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include "ModFile.hh"
|
#include "ModFile.hh"
|
||||||
|
#include "ConfigFile.hh"
|
||||||
|
|
||||||
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
|
ModFile::ModFile() : expressions_tree(symbol_table, num_constants, external_functions_table),
|
||||||
dynamic_model(symbol_table, num_constants, external_functions_table),
|
dynamic_model(symbol_table, num_constants, external_functions_table),
|
||||||
|
@ -344,7 +345,7 @@ ModFile::computingPass(bool no_tmp_terms)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ModFile::writeOutputFiles(const string &basename, bool clear_all
|
ModFile::writeOutputFiles(const string &basename, bool clear_all, const ConfigFile &config_file
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, bool cygwin, bool msvc
|
, bool cygwin, bool msvc
|
||||||
#endif
|
#endif
|
||||||
|
@ -419,6 +420,8 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all
|
||||||
<< "options_.bytecode=" << byte_code << ";" << endl
|
<< "options_.bytecode=" << byte_code << ";" << endl
|
||||||
<< "options_.use_dll=" << use_dll << ";" << endl;
|
<< "options_.use_dll=" << use_dll << ";" << endl;
|
||||||
|
|
||||||
|
config_file.writeCluster(mOutputFile);
|
||||||
|
|
||||||
if (byte_code)
|
if (byte_code)
|
||||||
mOutputFile << "if exist('bytecode') ~= 3" << endl
|
mOutputFile << "if exist('bytecode') ~= 3" << endl
|
||||||
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
|
<< " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.')" << endl
|
||||||
|
@ -530,8 +533,11 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all
|
||||||
if (block && !byte_code)
|
if (block && !byte_code)
|
||||||
mOutputFile << "rmpath " << basename << ";" << endl;
|
mOutputFile << "rmpath " << basename << ";" << endl;
|
||||||
|
|
||||||
mOutputFile << "save('" << basename << "_results.mat', 'oo_', 'M_', 'options_');" << endl
|
mOutputFile << "save('" << basename << "_results.mat', 'oo_', 'M_', 'options_');" << endl;
|
||||||
<< "diary off" << endl
|
|
||||||
|
config_file.writeEndParallel(mOutputFile);
|
||||||
|
|
||||||
|
mOutputFile << "diary off" << endl
|
||||||
<< endl << "disp(['Total computing time : ' dynsec2hms(toc) ]);" << endl;
|
<< endl << "disp(['Total computing time : ' dynsec2hms(toc) ]);" << endl;
|
||||||
|
|
||||||
mOutputFile.close();
|
mOutputFile.close();
|
||||||
|
|
|
@ -33,6 +33,7 @@ using namespace std;
|
||||||
#include "SteadyStateModel.hh"
|
#include "SteadyStateModel.hh"
|
||||||
#include "Statement.hh"
|
#include "Statement.hh"
|
||||||
#include "ExternalFunctionsTable.hh"
|
#include "ExternalFunctionsTable.hh"
|
||||||
|
#include "ConfigFile.hh"
|
||||||
|
|
||||||
//! The abstract representation of a "mod" file
|
//! The abstract representation of a "mod" file
|
||||||
class ModFile
|
class ModFile
|
||||||
|
@ -106,7 +107,7 @@ public:
|
||||||
\param clear_all Should a "clear all" instruction be written to output ?
|
\param clear_all Should a "clear all" instruction be written to output ?
|
||||||
\param msvc Should the MEX command of use_dll be adapted for MSVC?
|
\param msvc Should the MEX command of use_dll be adapted for MSVC?
|
||||||
*/
|
*/
|
||||||
void writeOutputFiles(const string &basename, bool clear_all
|
void writeOutputFiles(const string &basename, bool clear_all, const ConfigFile &config_file
|
||||||
#if defined(_WIN32) || defined(__CYGWIN32__)
|
#if defined(_WIN32) || defined(__CYGWIN32__)
|
||||||
, bool cygwin, bool msvc
|
, bool cygwin, bool msvc
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue