2015-06-24 20:58:17 +00:00
|
|
|
#include <sys/time.h>
|
|
|
|
|
2015-06-01 15:28:29 +00:00
|
|
|
#include "trick/MonteCarlo.hh"
|
|
|
|
#include "trick/command_line_protos.h"
|
|
|
|
#include "trick/message_proto.h"
|
|
|
|
#include "trick/message_type.h"
|
|
|
|
#include "trick/tc_proto.h"
|
|
|
|
#include "trick/exec_proto.h"
|
2015-02-26 15:02:31 +00:00
|
|
|
|
|
|
|
/** @par Detailed Design: */
|
|
|
|
void Trick::MonteCarlo::master_shutdown() {
|
|
|
|
|
|
|
|
/** <ul><li> Run the user-defined shutdown jobs. */
|
|
|
|
run_queue(&master_shutdown_queue, "in master_shutdown queue") ;
|
|
|
|
|
|
|
|
/** <ul><li> Shutdown the active slaves. */
|
|
|
|
shutdown_slaves() ;
|
|
|
|
|
|
|
|
/** <li> Shut down the sockets. */
|
|
|
|
tc_disconnect(&listen_device);
|
|
|
|
tc_disconnect(&connection_device);
|
|
|
|
|
|
|
|
struct timeval time_val;
|
|
|
|
gettimeofday(&time_val, NULL) ;
|
|
|
|
end_time = time_val.tv_sec + (double)time_val.tv_usec / 1000000;
|
|
|
|
|
|
|
|
/** <li> Print the statistics. */
|
|
|
|
if (!except_file.empty()) {
|
|
|
|
message_publish(MSG_INFO, "SIMULATION TERMINATED IN\n");
|
|
|
|
message_publish(MSG_INFO, " PROCESS: %d\n", exec_get_process_id());
|
|
|
|
message_publish(MSG_INFO, " ROUTINE: %s\n", except_file.c_str());
|
|
|
|
message_publish(MSG_INFO, " DIAGNOSTIC: %s\n\n", except_message.c_str());
|
|
|
|
}
|
|
|
|
FILE *file_ptr;
|
|
|
|
if (open_file(run_directory + std::string("/run_summary"), &file_ptr) == -1) exit(-2) ;
|
|
|
|
print_statistics(&file_ptr) ;
|
|
|
|
print_statistics(&stdout) ;
|
|
|
|
fclose(file_ptr) ;
|
|
|
|
|
2016-08-03 20:01:03 +00:00
|
|
|
if ( !except_return and failed_runs.size() > 0 ) {
|
|
|
|
except_return = -2 ;
|
|
|
|
}
|
|
|
|
|
2015-02-26 15:02:31 +00:00
|
|
|
exit(except_return);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Trick::MonteCarlo::shutdown_slaves() {
|
|
|
|
|
2018-07-25 18:05:10 +00:00
|
|
|
if (verbosity >= MC_INFORMATIONAL) {
|
2015-02-26 15:02:31 +00:00
|
|
|
message_publish(MSG_INFO, "Monte [Master] Simulation complete. Shutting down slaves.\n\n") ;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::vector<MonteSlave *>::size_type i = 0; i < slaves.size() ; ++i) {
|
2018-07-25 18:05:10 +00:00
|
|
|
slaves[i]->state = MonteSlave::MC_FINISHED;
|
2015-02-26 15:02:31 +00:00
|
|
|
connection_device.hostname = (char*)slaves[i]->machine_name.c_str();
|
|
|
|
connection_device.port = slaves[i]->port;
|
|
|
|
if (tc_connect(&connection_device) == TC_SUCCESS) {
|
2018-07-25 18:05:10 +00:00
|
|
|
int command = htonl(MonteSlave::MC_SHUTDOWN);
|
2015-02-26 15:02:31 +00:00
|
|
|
tc_write(&connection_device, (char*)&command, sizeof(command));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-18 21:08:47 +00:00
|
|
|
|
2015-02-26 15:02:31 +00:00
|
|
|
void Trick::MonteCarlo::print_statistics(FILE** fp) {
|
|
|
|
|
|
|
|
fprintf(*fp,
|
2019-06-21 19:02:03 +00:00
|
|
|
"\nMonte Carlo complete: %u runs (%zu successful) (%zu non-zero exit status) (%zu errors) (%u out of range)\n",
|
|
|
|
num_runs, num_results - failed_runs.size() - error_runs.size(), failed_runs.size(),
|
|
|
|
error_runs.size(), num_runs - num_results);
|
2015-02-26 15:02:31 +00:00
|
|
|
|
|
|
|
fprintf(*fp, "\nMachine work unit breakdown:\n");
|
|
|
|
fprintf(*fp, "----------------------------------------------------------------------\n");
|
|
|
|
fprintf(*fp, "%25s %7s (%7s) %12s %12s\n",
|
|
|
|
"machine", "units", "units %", "cpu_time (s)", "cpu/unit (s)");
|
|
|
|
fprintf(*fp, "----------------------------------------------------------------------\n");
|
|
|
|
|
|
|
|
double total_time = 0.0;
|
|
|
|
for (std::vector<MonteSlave *>::size_type j = 0; j < slaves.size(); ++j) {
|
|
|
|
fprintf(*fp, "%3d. %20s %7u (%6.2f%%) %12.2lf %12.2lf\n",
|
|
|
|
slaves[j]->id, slaves[j]->machine_name.c_str(),
|
|
|
|
slaves[j]->num_results,
|
|
|
|
num_results ? slaves[j]->num_results / (float)num_results * 100 : 0,
|
|
|
|
slaves[j]->cpu_time,
|
|
|
|
slaves[j]->num_results ? slaves[j]->cpu_time / slaves[j]->num_results : 0);
|
|
|
|
total_time += slaves[j]->cpu_time;
|
|
|
|
}
|
|
|
|
double monte_time = end_time - start_time;
|
|
|
|
double average_time = actual_num_runs ? total_time / actual_num_runs : 0;
|
|
|
|
double effective_time = actual_num_runs ? monte_time / actual_num_runs : 0;
|
|
|
|
double speed_up = total_time / monte_time;
|
|
|
|
double efficency = speed_up * 100.0 / slaves.size();
|
|
|
|
|
|
|
|
fprintf(*fp, "\nTotal monte carlo time taken: %.2lf\n", monte_time);
|
|
|
|
fprintf(*fp, "Actual average time per unit (sum of CPU time / number of runs): %.2lf\n", average_time);
|
|
|
|
fprintf(*fp, "Effective average time per unit (total time / number of runs): %.2lf\n", effective_time);
|
|
|
|
fprintf(*fp, "Speedup (sum of CPU time / total time): %.2lf\n", speed_up);
|
|
|
|
fprintf(*fp, "Efficency (speedup / num slaves): %.2lf%%\n", efficency);
|
|
|
|
|
|
|
|
if (failed_runs.size()) {
|
2019-06-21 19:02:03 +00:00
|
|
|
fprintf(*fp, "\nThe following runs completed with a non-zero process exit status:\n");
|
|
|
|
for (const MonteRun* run : failed_runs) {
|
|
|
|
fprintf(*fp, "RUN_%05d\n", run->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error_runs.size()) {
|
|
|
|
fprintf(*fp, "\nThe following runs failed to complete:\n");
|
|
|
|
for (const MonteRun* run : error_runs) {
|
|
|
|
fprintf(*fp, "RUN_%05d MonteRun::ExitStatus = %s (%d)\n", run->id,
|
2021-10-18 21:08:47 +00:00
|
|
|
run->exit_status_string(), run->exit_status);
|
2015-02-26 15:02:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|