50 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 52 #pragma comment(lib, "ws2_32.lib") 59 ValueTolerance::ValueTolerance() {
67 ValueTolerance::ValueTolerance(
double val,
double tol) {
75 ValueTolerance::ValueTolerance(
double val,
double low,
double up) {
80 use_tolerance =
false;
83 ValueTolerance::ValueTolerance(std::string str) {
87 bool ValueTolerance::operator ==(ValueTolerance& rhs) {
88 return (value == rhs.value) &&
89 (tolerance == rhs.tolerance) &&
90 (lower == rhs.lower) &&
91 (upper == rhs.upper) &&
92 (use_tolerance == rhs.use_tolerance);
95 std::string ValueTolerance::as_string(){
96 std::ostringstream strs;
98 strs << value <<
" , " << tolerance;
100 strs << value <<
" , " << lower <<
" , " << upper;
104 void ValueTolerance::from_string(
const std::string& valtol_str) {
105 std::string value_str = valtol_str.substr(0,valtol_str.find(
","));
106 value = atof(value_str.c_str());
107 std::string tol_str = valtol_str.substr(valtol_str.find(
",")+1);
108 if(tol_str.find(
",")<=tol_str.length()) {
109 use_tolerance =
false;
110 std::string lower_str = tol_str.substr(0,tol_str.find(
","));
111 lower = atof(lower_str.c_str());
112 std::string upper_str = tol_str.substr(tol_str.find(
",")+1);
113 upper = atof(upper_str.c_str());
115 use_tolerance =
true;
116 tolerance = atof(tol_str.c_str());
120 XMLTestNode::XMLTestNode():XMLObject() {}
122 XMLTestNode::XMLTestNode(
const std::string &tag):XMLObject(tag) {}
124 XMLTestNode::XMLTestNode(XMLObjectImplem *ptr):XMLObject(ptr) {}
126 XMLTestNode::XMLTestNode(XMLObject obj):XMLObject(obj) {}
128 void XMLTestNode::addDouble (
const std::string &name,
double val) {
129 addAttribute<double>(name,val);
132 void XMLTestNode::addInt (
const std::string &name,
int val) {
133 addAttribute<int>(name,val);
136 void XMLTestNode::addBool (
const std::string &name,
bool val) {
137 addAttribute<bool>(name,val);
140 void XMLTestNode::addValueTolerance(
const std::string &name, ValueTolerance val){
141 addAttribute<std::string>(name,val.as_string());
144 void XMLTestNode::addString (
const std::string &name, std::string val) {
145 addAttribute<std::string>(name,val);
148 bool XMLTestNode::hasChild(
const std::string &name)
const {
159 void XMLTestNode::appendContentLine(
const size_t& i,
const std::string &str) {
160 ptr_->appendContentLine(i,str);
163 XMLTestNode XMLTestNode::getChild(
const std::string &name)
const {
172 XMLTestNode XMLTestNode::getChild(
const int &i)
const {
176 const XMLObject* XMLTestNode::xml_object()
const {
180 bool XMLTestNode::hasSameElements(XMLTestNode
const & lhs)
const {
184 (
getTag().compare(lhs.getTag())!=0))
return false;
188 if( (!lhs.hasChild(child.getTag())) ||
189 (!child.hasSameElements(lhs.getChild(child.getTag()))) )
return false;
193 if(
getContentLine(i).compare(lhs.getContentLine(i))!=0)
return false;
201 std::string cpuname(
"Undefined");
202 unsigned int threads = 0;
203 unsigned int cores_per_socket = 0;
204 unsigned int highest_socketid = 0;
207 std::ifstream cpuinfo(
"/proc/cpuinfo");
209 if((cpuinfo.rdstate()&cpuinfo.failbit)) std::cout<<
"Failed to open filen\n";
210 while (!cpuinfo.eof() && !(cpuinfo.rdstate()&cpuinfo.failbit)) {
211 getline (cpuinfo,line);
212 if (line.find(
"model name") < line.size()) {
213 cpuname = line.substr(line.find(
":")+2);
216 if (line.find(
"physical id") < line.size()) {
217 unsigned int socketid = atoi(line.substr(line.find(
":")+2).c_str());
218 highest_socketid = highest_socketid>socketid?highest_socketid:socketid;
220 if (line.find(
"cpu cores") < line.size()) {
221 cores_per_socket = atoi(line.substr(line.find(
":")+2).c_str());
227 XMLTestNode machine_config(
"MachineConfiguration");
229 machine_config.addString(
"Compiler", TEUCHOS_COMPILER_NAME);
230 machine_config.addInt(
"Compiler_Version", TEUCHOS_COMPILER_VERSION);
231 machine_config.addString(
"CPU_Name", cpuname);
232 machine_config.addInt(
"CPU_Sockets", highest_socketid+1);
233 machine_config.addInt(
"CPU_Cores_Per_Socket", cores_per_socket);
234 machine_config.addInt(
"CPU_Total_HyperThreads", threads);
235 return machine_config;
241 const std::string filename,
242 const std::string ext_hostname)
246 bool is_new_config =
true;
251 if (std::ifstream (filename.c_str ())) {
257 memset (hostname, 0, 256);
258 if (ext_hostname.empty ()) {
259 gethostname (hostname, 255);
261 strncat (hostname, ext_hostname.c_str (), 255);
264 XMLTestNode new_test_entry = new_test.getChild (
"TestEntry");
270 if (database.hasChild (hostname)) {
271 XMLTestNode machine = database.getChild (hostname);
277 configuration.
getTag ().compare (
"Configuration") != 0,
278 std::runtime_error,
"Unexpected Tag \"" << configuration.
getTag ()
279 <<
"\"; only children with Tag = \"Configuration\" are allowed in a " 283 ! configuration.hasChild (
"MachineConfiguration") ||
284 ! configuration.hasChild (
"Tests"),
286 "A Configuration needs to have a child \"MachineConfiguration\" and a " 289 XMLTestNode machine_configuration = configuration.getChild (
"MachineConfiguration");
290 XMLTestNode old_tests = configuration.getChild (
"Tests");
292 if (machine_configuration.hasSameElements (machine_config)) {
293 is_new_config =
false;
296 if (old_tests.hasChild (new_test.
getTag ())) {
300 int new_test_config = -1;
301 for (
int k = 0; k < old_test.
numChildren (); ++k) {
302 XMLTestNode old_test_entry = old_test.getChild (k);
305 ! old_test_entry.hasChild (
"TestConfiguration") ||
306 ! new_test_entry.hasChild (
"TestResults"),
307 std::runtime_error,
"A TestEntry needs to have a child " 308 "\"TestConfiguration\" and a child \"TestResults\".");
310 if (old_test_entry.getChild (
"TestConfiguration").hasSameElements (new_test_entry.getChild (
"TestConfiguration"))) {
315 if (new_test_config < 0) {
317 return_value = PerfTestNewTestConfiguration;
319 bool deviation =
false;
320 XMLTestNode old_test_entry = old_test.getChild (new_test_config);
321 XMLTestNode old_results = old_test_entry.getChild (
"TestResults");
322 XMLTestNode new_results = new_test_entry.getChild (
"TestResults");
325 for (
int old_r = 0; old_r < old_results.
numChildren (); ++old_r) {
326 XMLTestNode result_entry = old_results.getChild (old_r);
329 bool exists = new_results.hasChild (result_entry.
getTag ());
335 if((result_entry.
getTag().find(
"Time")==0) || (result_entry.
getTag().find(
"Result")==0)) {
339 if(old_valtol.use_tolerance) {
340 double diff = old_valtol.value - new_valtol.value;
343 double normalization = old_valtol.value;
344 normalization*=normalization;
346 if(normalization==0?diff>0:diff/normalization>old_valtol.tolerance*old_valtol.tolerance) {
348 std::cout << std::endl
349 <<
"DeviationA in Test: \"" << old_test.
getTag()
350 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
351 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
352 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
355 if( (old_valtol.lower>new_valtol.value) || (old_valtol.upper<new_valtol.value)) {
357 std::cout << std::endl
358 <<
"DeviationB in Test: \"" << old_test.
getTag()
359 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
360 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
361 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
366 if(oldv_str.compare(new_results.getChild(result_entry.
getTag()).getContentLine(0))!=0) {
368 std::cout << std::endl
369 <<
"DeviationC in Test: \"" << old_test.
getTag()
370 <<
"\" for entry \"" << result_entry.
getTag() <<
"\"" << std::endl;
371 std::cout <<
" Existing Value: \"" << oldv_str <<
"\"" << std::endl;
372 std::cout <<
" New Value: \"" << new_results.getChild(result_entry.
getTag()).getContentLine(0) <<
"\"" << std::endl << std::endl;
378 std::cout <<
"Error New test has same name as an existing one, but one of the old entries is missing." << std::endl;
383 if(deviation) { return_value = PerfTestFailed; }
387 for(
int new_r = 0; new_r < new_results.
numChildren() ; new_r++) {
388 if(!old_results.hasChild(new_results.getChild(new_r).
getTag())) {
389 old_results.
addChild(new_results.getChild(new_r));
393 return_value = PerfTestUpdatedTest;
400 return_value = PerfTestNewTest;
415 return_value = PerfTestNewConfiguration;
430 return_value = PerfTestNewMachine;
434 if(return_value>PerfTestPassed) {
435 std::ofstream fout(filename.c_str());
436 fout << database << std::endl;
#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.
const XMLObject & getChild(int i) const
Return the i-th child node.
XMLObject()
Empty constructor.
const std::string & getContentLine(int i) const
Return the i-th line of character content stored in this node.
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.
bool isEmpty() const
Find out if a node is empty.
int numContentLines() const
Return the number of lines of character content stored in this node.
const std::string & getTag() const
Return the tag of the current node.
PerfTestResult
ReturnValues for PerfTest_CheckOrAdd_Test.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
Subclass of XMLObject used by the performance archive.
int numChildren() const
Return the number of child nodes owned by 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.