Skip to content

Commit 295d07b

Browse files
author
Theodore Bugnet
committed
Added some extra error handling to benchmarker and fixed CMakeLists; updated readme with better quickstart.
1 parent d4a81c8 commit 295d07b

3 files changed

Lines changed: 49 additions & 12 deletions

File tree

CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-g")# -pg")
1414
SET(CMAKE_CXX_FLAGS_RELEASE "-O3")
1515

1616
#Customise these values to customise the installation
17-
SET(INSTALL_PREF "../../install-test/") #Unset for installation to default binary directory, or change to a different portable directory
17+
SET(INSTALL_PREF "../../../install/") #Unset for installation to default binary directory, or change to a different portable directory
1818
SET(STORE_PATH "./store/") #Unless installing to a self-contained location, this should probably be an absolute path, e.g. inside ~
1919
SET(CONF_PREFIX "./conf/") #Same for this, alternatively set this to a path in /etc/
2020
SET(CONF_PATH_ANALYSER "./graph_analyser.conf") #The next three are names of files inside CONF_PREFIX
@@ -36,14 +36,14 @@ if (Boost_FOUND)
3636
target_compile_definitions(graph_analyser PRIVATE CONF_PATH="${CONF_PREFIX}${CONF_PATH_ANALYSER}")
3737
target_compile_definitions(graph_mapper PRIVATE CONF_PATH="${CONF_PREFIX}${CONF_PATH_MAPPER}")
3838
target_compile_definitions(report_generator PRIVATE CONF_PATH="${CONF_PREFIX}${CONF_PATH_GENERATOR}" STORE_PATH="${STORE_PATH}")
39-
target_compile_definitions(benchmarker PRIVATE CONF_PATH="${CONF_PREFIX}${CONF_PATH_BENCHMARKER}" BIN_PATH="${INSTALL_PREF}")
39+
target_compile_definitions(benchmarker PRIVATE CONF_PATH="${CONF_PREFIX}${CONF_PATH_BENCHMARKER}" BIN_PATH=".")
4040
target_compile_definitions(common PRIVATE STORE_PATH="${STORE_PATH}")
4141
set(CMAKE_INSTALL_PREFIX ${INSTALL_PREF} CACHE PATH "..." FORCE)
4242
install(TARGETS graph_analyser RUNTIME DESTINATION .)
4343
install(TARGETS graph_mapper RUNTIME DESTINATION .)
4444
install(TARGETS benchmarker RUNTIME DESTINATION .)
4545
install(TARGETS report_generator RUNTIME DESTINATION .)
4646
install(DIRECTORY store DESTINATION . USE_SOURCE_PERMISSIONS MESSAGE_NEVER)
47-
install(PROGRAMS benchmarker/external/exts/compare-extensions DESTINATION ${INSTALL_PREF})
48-
install(PROGRAMS benchmarker/external/runsolver/runsolver DESTINATION ${INSTALL_PREF})
47+
install(PROGRAMS benchmarker/external/exts/compare-extensions DESTINATION .)
48+
install(PROGRAMS benchmarker/external/runsolver/runsolver DESTINATION .)
4949
endif()

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ AAF and solver benchmarking and analysis toolkit.
44
# Quick start
55
The archive contains a full, ready to use environment in the `install-final` folder. To rebuild from source: ensure the necessary dependencies (CMake, Boost, a recent version of GCC/Clang) are installed; in the root `CMakeLists.txt`, configure `INSTALL\_PREF` as desired; `cd build` and run `make install`.
66

7+
Then place some graphs into store/graphs (or use the -g/-d options to specify graphs), run `graph\_analyser` to generate metric scores and/or `benchmarker` with proper options (see `benchmarker -h`) to generate solver performance data, and then either peruse the store or generate an report on the data using `report\_generator -t <type> [other options]` (see `report\_generator -h` for more information).
8+
79
## Installation
810
### Prerequisites
911
* Cmake
@@ -76,5 +78,17 @@ As an alternative, any executable file in the directory `store/external-metrics`
7678

7779
This allows new metrics to be easily created without recompiling any other code; it also gives a lot of flexibility in how metrics are developed - the executable could be anything from a Python script to a wrapper calling an external tool located elsewhere.
7880

81+
### Graph hashing
82+
Graphs are hashed with SpookyHash (http://burtleburtle.net/bob/hash/spooky.html) to ensure no duplication. `graph_mapper` can be used to quickly check what a graph's hash is, or what graph file a hash belongs to. The file `store/graphhashmap` stores key-value pairs between graph filepath and hash, as a cache, and can also be easily explored or `grep`ed manually.
83+
84+
## Store
85+
The store is where all the data is saved; here is an overview of its structure.
86+
### `graph-scores`
87+
Each file here corresponds to a graph. The format of the files should be self-explanatory: each line gives the value of a metric.
88+
### `bench-solutions`
89+
Here the solutions for every problem are stored, in subdirectories corresponding to each graph. Each problem has its own file, named after the problem, containing the output of the reference solver used verbatim
90+
### `benchmarks`
91+
The output of benchmark runs. Each subfolder here corresponds to a solver. Inside a solver's folder, there is a subfolder for every run ID, inside of which the actual run information is stored. Each benchmark run has a subfolder for every graph, inside which each problem has either 1 or 2 corresponding files named after it: a `<PROBLEM>.stat` file and a `<PROBLEM>.output` file. The latter contains the solver output verbatim, and may not be kept depending on the options passed to `benchmarker` (by default, only outputs for incorrect solutions are kept; you can also specify the max size of solutions to keep). The .stat file contains the performance data of the solver.
92+
7993
# License
8094
This program is released under the GNU General Public License, version 3 or (at your option) any later version. For more information, see LICENSE.txt or https://www.gnu.org/licenses/.

benchmarker/main.cxx

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
namespace po = boost::program_options;
3535
namespace fs = std::filesystem;
3636

37+
const int magic_number = 143; //randomly selected, used as special return value
38+
3739
unsigned long getSizeInBytes(std::string sizeWithSuffix)
3840
{
3941
unsigned long ret = 0;
@@ -316,11 +318,15 @@ int main(int argc, char** argv)
316318
{
317319
if (referenceSolverpath == "")
318320
{ if (!quiet)
319-
{ std::cout << "No reference solver specified and no solution for graph " << graphFile
321+
{ std::cout << "INFO: No reference solver specified and no solution for graph " << graphFile
320322
<< " and problem " << fullproblem << "; skipping." << std::endl;
321323
continue;
322324
}
323325
}
326+
else if (!fs::exists(referenceSolverpath) || !(fs::is_regular_file(referenceSolverpath) || fs::is_symlink(referenceSolverpath)))
327+
{ std::cerr << "WARNING: Reference solver path does not point to a file. Double-check the filepath. Skipping graphs with no existing solutions." << std::endl;
328+
continue;
329+
}
324330
else
325331
{ if (verbose)
326332
{ std::cout << " No solution exists; running reference solver..." << std::endl;
@@ -341,7 +347,18 @@ int main(int argc, char** argv)
341347
continue;
342348
}
343349
else if (pid > 0) //parent
344-
{ wait(NULL);
350+
{ int status;
351+
wait(&status);
352+
if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status) == magic_number))
353+
{ std::cerr << "ERROR: Unable to execute reference solver! Skipping graph." << std::endl;
354+
if(!fs::remove(solfp))
355+
{ std::cerr << "Could not remove solution file..." << std::endl;
356+
}
357+
continue;
358+
}
359+
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
360+
{ std::cerr << "WARNING: Reference solver exited with non-zero status: " << WEXITSTATUS(status) << std::endl;
361+
}
345362
}
346363
else //child
347364
{ if (dup2(outfd, STDOUT_FILENO) < 0)
@@ -364,7 +381,7 @@ int main(int argc, char** argv)
364381
args[argvct.size()] = NULL;
365382

366383
execv(referenceSolverpath.c_str(), (char**)args);
367-
std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAA" << std::endl;
384+
return magic_number;
368385
}
369386
}
370387
}
@@ -384,7 +401,16 @@ int main(int argc, char** argv)
384401
continue;
385402
}
386403
else if (pid > 0) //parent
387-
{ wait(NULL);
404+
{ int status;
405+
wait(&status);
406+
if (!WIFEXITED(status) || (WIFEXITED(status) && WEXITSTATUS(status) == magic_number))
407+
{ std::cerr << "FATAL ERROR: Failed to execute runsolver. Aborting!" << std::endl;
408+
continue;
409+
}
410+
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
411+
{ std::cerr << "WARNING: Runsolver exited with non-zero status. Skipping further processing." << std::endl;
412+
continue;
413+
}
388414
}
389415
else //child
390416
{ const char* runsolver = BIN_PATH "/runsolver";
@@ -420,7 +446,7 @@ int main(int argc, char** argv)
420446
args[argvct.size()] = NULL;
421447

422448
execv(runsolver, (char**)args);
423-
std::cout << "AAAAAAAAAAAAAAAAAAAAAAAAAA" << std::endl;
449+
return magic_number;
424450
}
425451

426452
//runsolver is done
@@ -458,9 +484,6 @@ int main(int argc, char** argv)
458484
<< ". No correctness report will be generated. Error message: " << status << std::endl;
459485
in.close();
460486
is_correct = false; //provide default
461-
if (fs::file_size(outfp) >= saveMaxSize)
462-
{ fs::remove(outfp);
463-
}
464487
}
465488
else
466489
{ is_correct = (status == "OK"? true : false);

0 commit comments

Comments
 (0)