58 ValueTolerance::ValueTolerance() {
66 ValueTolerance::ValueTolerance(
double val,
double tol) {
74 ValueTolerance::ValueTolerance(
double val,
double low,
double up) {
79 use_tolerance =
false;
82 ValueTolerance::ValueTolerance(std::string str) {
86 bool ValueTolerance::operator ==(ValueTolerance& rhs) {
87 return (value == rhs.value) &&
88 (tolerance == rhs.tolerance) &&
89 (lower == rhs.lower) &&
90 (upper == rhs.upper) &&
91 (use_tolerance == rhs.use_tolerance);
94 std::string ValueTolerance::as_string(){
95 std::ostringstream strs;
97 strs << value <<
" , " << tolerance;
99 strs << value <<
" , " << lower <<
" , " << upper;
103 void ValueTolerance::from_string(
const std::string& valtol_str) {
104 std::string value_str = valtol_str.substr(0,valtol_str.find(
","));
105 value = atof(value_str.c_str());
106 std::string tol_str = valtol_str.substr(valtol_str.find(
",")+1);
107 if(tol_str.find(
",")<=tol_str.length()) {
108 use_tolerance =
false;
109 std::string lower_str = tol_str.substr(0,tol_str.find(
","));
110 lower = atof(lower_str.c_str());
111 std::string upper_str = tol_str.substr(tol_str.find(
",")+1);
112 upper = atof(upper_str.c_str());
114 use_tolerance =
true;
115 tolerance = atof(tol_str.c_str());
119 XMLTestNode::XMLTestNode():XMLObject() {}
121 XMLTestNode::XMLTestNode(
const std::string &tag):XMLObject(tag) {}
123 XMLTestNode::XMLTestNode(XMLObjectImplem *ptr):XMLObject(ptr) {}
125 XMLTestNode::XMLTestNode(XMLObject obj):XMLObject(obj) {}
127 void XMLTestNode::addDouble (
const std::string &name,
double val) {
128 addAttribute<double>(name,val);
131 void XMLTestNode::addInt (
const std::string &name,
int val) {
132 addAttribute<int>(name,val);
135 void XMLTestNode::addBool (
const std::string &name,
bool val) {
136 addAttribute<bool>(name,val);
139 void XMLTestNode::addValueTolerance(
const std::string &name, ValueTolerance val){
140 addAttribute<std::string>(name,val.as_string());
143 void XMLTestNode::addString (
const std::string &name, std::string val) {
144 addAttribute<std::string>(name,val);
147 bool XMLTestNode::hasChild(
const std::string &name)
const {
158 void XMLTestNode::appendContentLine(
const size_t& i,
const std::string &str) {
159 ptr_->appendContentLine(i,str);
162 XMLTestNode XMLTestNode::getChild(
const std::string &name)
const {
171 XMLTestNode XMLTestNode::getChild(
const int &i)
const {
175 const XMLObject* XMLTestNode::xml_object()
const {
179 bool XMLTestNode::hasSameElements(XMLTestNode
const & lhs)
const {
183 (
getTag().compare(lhs.getTag())!=0))
return false;
187 if( (!lhs.hasChild(child.getTag())) ||
188 (!child.hasSameElements(lhs.getChild(child.getTag()))) )
return false;
192 if(
getContentLine(i).compare(lhs.getContentLine(i))!=0)
return false;
200 std::string cpuname(
"Undefined");
201 unsigned int threads = 0;
202 unsigned int cores_per_socket = 0;
203 unsigned int highest_socketid = 0;
206 std::ifstream cpuinfo(
"/proc/cpuinfo");
208 if((cpuinfo.rdstate()&cpuinfo.failbit)) std::cout<<
"Failed to open filen\n";
209 while (!cpuinfo.eof() && !(cpuinfo.rdstate()&cpuinfo.failbit)) {
210 getline (cpuinfo,line);
211 if (line.find(
"model name") < line.size()) {
212 cpuname = line.substr(line.find(
":")+2);
215 if (line.find(
"physical id") < line.size()) {
216 unsigned int socketid = atoi(line.substr(line.find(
":")+2).c_str());
217 highest_socketid = highest_socketid>socketid?highest_socketid:socketid;
219 if (line.find(
"cpu cores") < line.size()) {
220 cores_per_socket = atoi(line.substr(line.find(
":")+2).c_str());
226 XMLTestNode machine_config(
"MachineConfiguration");
228 machine_config.addString(
"Compiler", TEUCHOS_COMPILER_NAME);
229 machine_config.addInt(
"Compiler_Version", TEUCHOS_COMPILER_VERSION);
230 machine_config.addString(
"CPU_Name", cpuname);
231 machine_config.addInt(
"CPU_Sockets", highest_socketid+1);
232 machine_config.addInt(
"CPU_Cores_Per_Socket", cores_per_socket);
233 machine_config.addInt(
"CPU_Total_HyperThreads", threads);
234 return machine_config;
240 const std::string filename,
241 const std::string ext_hostname)
245 bool is_new_config =
true;
250 if (std::ifstream (filename.c_str ())) {
256 memset (hostname, 0, 256);
257 if (ext_hostname.empty ()) {
258 gethostname (hostname, 255);
260 strncat (hostname, ext_hostname.c_str (), 255);
263 XMLTestNode new_test_entry = new_test.getChild (
"TestEntry");
269 if (database.hasChild (hostname)) {
270 XMLTestNode machine = database.getChild (hostname);
276 configuration.
getTag ().compare (
"Configuration") != 0,
277 std::runtime_error,
"Unexpected Tag \"" << configuration.
getTag ()
278 <<
"\"; only children with Tag = \"Configuration\" are allowed in a "
282 ! configuration.hasChild (
"MachineConfiguration") ||
283 ! configuration.hasChild (
"Tests"),
285 "A Configuration needs to have a child \"MachineConfiguration\" and a "
288 XMLTestNode machine_configuration = configuration.getChild (
"MachineConfiguration");
289 XMLTestNode old_tests = configuration.getChild (
"Tests");
291 if (machine_configuration.hasSameElements (machine_config)) {
292 is_new_config =
false;
295 if (old_tests.hasChild (new_test.
getTag ())) {
299 int new_test_config = -1;
300 for (
int k = 0; k < old_test.
numChildren (); ++k) {
301 XMLTestNode old_test_entry = old_test.getChild (k);
304 ! old_test_entry.hasChild (
"TestConfiguration") ||
305 ! new_test_entry.hasChild (
"TestResults"),
306 std::runtime_error,
"A TestEntry needs to have a child "
307 "\"TestConfiguration\" and a child \"TestResults\".");
309 if (old_test_entry.getChild (
"TestConfiguration").hasSameElements (new_test_entry.getChild (
"TestConfiguration"))) {
314 if (new_test_config < 0) {
316 return_value = PerfTestNewTestConfiguration;
318 bool deviation =
false;
319 XMLTestNode old_test_entry = old_test.getChild (new_test_config);
320 XMLTestNode old_results = old_test_entry.getChild (
"TestResults");
321 XMLTestNode new_results = new_test_entry.getChild (
"TestResults");
324 for (
int old_r = 0; old_r < old_results.
numChildren (); ++old_r) {
325 XMLTestNode result_entry = old_results.getChild (old_r);
328 bool exists = new_results.hasChild (result_entry.
getTag ());
334 if((result_entry.
getTag().find(
"Time")==0) || (result_entry.
getTag().find(
"Result")==0)) {
338 if(old_valtol.use_tolerance) {
339 double diff = old_valtol.value - new_valtol.value;
342 double normalization = old_valtol.value;
343 normalization*=normalization;
345 if(normalization==0?diff>0:diff/normalization>old_valtol.tolerance*old_valtol.tolerance) {
347 std::cout << std::endl
348 <<
"DeviationA in Test: \"" << old_test.
getTag()
349 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
350 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
351 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
354 if( (old_valtol.lower>new_valtol.value) || (old_valtol.upper<new_valtol.value)) {
356 std::cout << std::endl
357 <<
"DeviationB in Test: \"" << old_test.
getTag()
358 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
359 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
360 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
365 if(oldv_str.compare(new_results.getChild(result_entry.
getTag()).getContentLine(0))!=0) {
367 std::cout << std::endl
368 <<
"DeviationC in Test: \"" << old_test.
getTag()
369 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
370 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
371 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
377 std::cout <<
"Error New test has same name as an existing one, but one of the old entries is missing." << std::endl;
382 if(deviation) { return_value = PerfTestFailed; }
386 for(
int new_r = 0; new_r < new_results.
numChildren() ; new_r++) {
387 if(!old_results.hasChild(new_results.getChild(new_r).
getTag())) {
388 old_results.
addChild(new_results.getChild(new_r));
392 return_value = PerfTestUpdatedTest;
399 return_value = PerfTestNewTest;
414 return_value = PerfTestNewConfiguration;
429 return_value = PerfTestNewMachine;
433 if(return_value>PerfTestPassed) {
434 std::ofstream fout(filename.c_str());
435 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.