25 ValueTolerance::ValueTolerance() {
33 ValueTolerance::ValueTolerance(
double val,
double tol) {
41 ValueTolerance::ValueTolerance(
double val,
double low,
double up) {
46 use_tolerance =
false;
49 ValueTolerance::ValueTolerance(std::string str) {
53 bool ValueTolerance::operator ==(ValueTolerance& rhs) {
54 return (value == rhs.value) &&
55 (tolerance == rhs.tolerance) &&
56 (lower == rhs.lower) &&
57 (upper == rhs.upper) &&
58 (use_tolerance == rhs.use_tolerance);
61 std::string ValueTolerance::as_string(){
62 std::ostringstream strs;
64 strs << value <<
" , " << tolerance;
66 strs << value <<
" , " << lower <<
" , " << upper;
70 void ValueTolerance::from_string(
const std::string& valtol_str) {
71 std::string value_str = valtol_str.substr(0,valtol_str.find(
","));
72 value = atof(value_str.c_str());
73 std::string tol_str = valtol_str.substr(valtol_str.find(
",")+1);
74 if(tol_str.find(
",")<=tol_str.length()) {
75 use_tolerance =
false;
76 std::string lower_str = tol_str.substr(0,tol_str.find(
","));
77 lower = atof(lower_str.c_str());
78 std::string upper_str = tol_str.substr(tol_str.find(
",")+1);
79 upper = atof(upper_str.c_str());
82 tolerance = atof(tol_str.c_str());
86 XMLTestNode::XMLTestNode():XMLObject() {}
88 XMLTestNode::XMLTestNode(
const std::string &tag):XMLObject(tag) {}
90 XMLTestNode::XMLTestNode(XMLObjectImplem *ptr):XMLObject(ptr) {}
92 XMLTestNode::XMLTestNode(XMLObject obj):XMLObject(obj) {}
94 void XMLTestNode::addDouble (
const std::string &name,
double val) {
95 addAttribute<double>(name,val);
98 void XMLTestNode::addInt (
const std::string &name,
int val) {
99 addAttribute<int>(name,val);
102 void XMLTestNode::addBool (
const std::string &name,
bool val) {
103 addAttribute<bool>(name,val);
106 void XMLTestNode::addValueTolerance(
const std::string &name, ValueTolerance val){
107 addAttribute<std::string>(name,val.as_string());
110 void XMLTestNode::addString (
const std::string &name, std::string val) {
111 addAttribute<std::string>(name,val);
114 bool XMLTestNode::hasChild(
const std::string &name)
const {
125 void XMLTestNode::appendContentLine(
const size_t& i,
const std::string &str) {
126 ptr_->appendContentLine(i,str);
129 XMLTestNode XMLTestNode::getChild(
const std::string &name)
const {
138 XMLTestNode XMLTestNode::getChild(
const int &i)
const {
142 const XMLObject* XMLTestNode::xml_object()
const {
146 bool XMLTestNode::hasSameElements(XMLTestNode
const & lhs)
const {
150 (
getTag().compare(lhs.getTag())!=0))
return false;
154 if( (!lhs.hasChild(child.getTag())) ||
155 (!child.hasSameElements(lhs.getChild(child.getTag()))) )
return false;
159 if(
getContentLine(i).compare(lhs.getContentLine(i))!=0)
return false;
167 std::string cpuname(
"Undefined");
168 unsigned int threads = 0;
169 unsigned int cores_per_socket = 0;
170 unsigned int highest_socketid = 0;
173 std::ifstream cpuinfo(
"/proc/cpuinfo");
175 if((cpuinfo.rdstate()&cpuinfo.failbit)) std::cout<<
"Failed to open filen\n";
176 while (!cpuinfo.eof() && !(cpuinfo.rdstate()&cpuinfo.failbit)) {
177 getline (cpuinfo,line);
178 if (line.find(
"model name") < line.size()) {
179 cpuname = line.substr(line.find(
":")+2);
182 if (line.find(
"physical id") < line.size()) {
183 unsigned int socketid = atoi(line.substr(line.find(
":")+2).c_str());
184 highest_socketid = highest_socketid>socketid?highest_socketid:socketid;
186 if (line.find(
"cpu cores") < line.size()) {
187 cores_per_socket = atoi(line.substr(line.find(
":")+2).c_str());
193 XMLTestNode machine_config(
"MachineConfiguration");
195 machine_config.addString(
"Compiler", TEUCHOS_COMPILER_NAME);
196 machine_config.addInt(
"Compiler_Version", TEUCHOS_COMPILER_VERSION);
197 machine_config.addString(
"CPU_Name", cpuname);
198 machine_config.addInt(
"CPU_Sockets", highest_socketid+1);
199 machine_config.addInt(
"CPU_Cores_Per_Socket", cores_per_socket);
200 machine_config.addInt(
"CPU_Total_HyperThreads", threads);
201 return machine_config;
207 const std::string filename,
208 const std::string ext_hostname)
212 bool is_new_config =
true;
217 if (std::ifstream (filename.c_str ())) {
223 memset (hostname, 0, 256);
224 if (ext_hostname.empty ()) {
225 gethostname (hostname, 255);
227 strncat (hostname, ext_hostname.c_str (), 255);
230 XMLTestNode new_test_entry = new_test.getChild (
"TestEntry");
236 if (database.hasChild (hostname)) {
237 XMLTestNode machine = database.getChild (hostname);
243 configuration.
getTag ().compare (
"Configuration") != 0,
244 std::runtime_error,
"Unexpected Tag \"" << configuration.
getTag ()
245 <<
"\"; only children with Tag = \"Configuration\" are allowed in a "
249 ! configuration.hasChild (
"MachineConfiguration") ||
250 ! configuration.hasChild (
"Tests"),
252 "A Configuration needs to have a child \"MachineConfiguration\" and a "
255 XMLTestNode machine_configuration = configuration.getChild (
"MachineConfiguration");
256 XMLTestNode old_tests = configuration.getChild (
"Tests");
258 if (machine_configuration.hasSameElements (machine_config)) {
259 is_new_config =
false;
262 if (old_tests.hasChild (new_test.
getTag ())) {
266 int new_test_config = -1;
267 for (
int k = 0; k < old_test.
numChildren (); ++k) {
268 XMLTestNode old_test_entry = old_test.getChild (k);
271 ! old_test_entry.hasChild (
"TestConfiguration") ||
272 ! new_test_entry.hasChild (
"TestResults"),
273 std::runtime_error,
"A TestEntry needs to have a child "
274 "\"TestConfiguration\" and a child \"TestResults\".");
276 if (old_test_entry.getChild (
"TestConfiguration").hasSameElements (new_test_entry.getChild (
"TestConfiguration"))) {
281 if (new_test_config < 0) {
283 return_value = PerfTestNewTestConfiguration;
285 bool deviation =
false;
286 XMLTestNode old_test_entry = old_test.getChild (new_test_config);
287 XMLTestNode old_results = old_test_entry.getChild (
"TestResults");
288 XMLTestNode new_results = new_test_entry.getChild (
"TestResults");
291 for (
int old_r = 0; old_r < old_results.
numChildren (); ++old_r) {
292 XMLTestNode result_entry = old_results.getChild (old_r);
295 bool exists = new_results.hasChild (result_entry.
getTag ());
301 if((result_entry.
getTag().find(
"Time")==0) || (result_entry.
getTag().find(
"Result")==0)) {
305 if(old_valtol.use_tolerance) {
306 double diff = old_valtol.value - new_valtol.value;
309 double normalization = old_valtol.value;
310 normalization*=normalization;
312 if(normalization==0?diff>0:diff/normalization>old_valtol.tolerance*old_valtol.tolerance) {
314 std::cout << std::endl
315 <<
"DeviationA in Test: \"" << old_test.
getTag()
316 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
317 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
318 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
321 if( (old_valtol.lower>new_valtol.value) || (old_valtol.upper<new_valtol.value)) {
323 std::cout << std::endl
324 <<
"DeviationB in Test: \"" << old_test.
getTag()
325 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
326 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
327 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
332 if(oldv_str.compare(new_results.getChild(result_entry.
getTag()).getContentLine(0))!=0) {
334 std::cout << std::endl
335 <<
"DeviationC in Test: \"" << old_test.
getTag()
336 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
337 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
338 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
344 std::cout <<
"Error New test has same name as an existing one, but one of the old entries is missing." << std::endl;
349 if(deviation) { return_value = PerfTestFailed; }
353 for(
int new_r = 0; new_r < new_results.
numChildren() ; new_r++) {
354 if(!old_results.hasChild(new_results.getChild(new_r).
getTag())) {
355 old_results.
addChild(new_results.getChild(new_r));
359 return_value = PerfTestUpdatedTest;
366 return_value = PerfTestNewTest;
381 return_value = PerfTestNewConfiguration;
396 return_value = PerfTestNewMachine;
400 if(return_value>PerfTestPassed) {
401 std::ofstream fout(filename.c_str());
402 fout << database << std::endl;
const std::string & getTag() const
Return the tag of the current node.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
void addChild(const XMLObject &child)
Add a child node to the node.
bool isEmpty() const
Find out if a node is empty.
XMLObject()
Empty constructor.
ValueTolerance is a struct to keep a tuple of value and a tolerance. The tolerance can be either expr...
Tools for an XML-based performance test archive.
PerfTestResult
ReturnValues for PerfTest_CheckOrAdd_Test.
int numChildren() const
Return the number of child nodes owned by this node.
Subclass of XMLObject used by the performance archive.
int numContentLines() const
Return the number of lines of character content stored in this node.
const XMLObject & getChild(int i) const
Return the i-th child node.
const std::string & getContentLine(int i) const
Return the i-th line of character content stored in this node.
PerfTestResult PerfTest_CheckOrAdd_Test(XMLTestNode machine_config, XMLTestNode new_test, const std::string filename, const std::string ext_hostname)
Check whether a test is present and match an existing test in an archive.
XMLTestNode PerfTest_MachineConfig()
PerfTest_MachineConfig generates a basic machine configuration XMLTestNode.
An object representation of a subset of XML data.