#include "XSbench_header.h" #ifdef MPI #include #endif // Prints program logo void logo(int version) { border_print(); printf( " __ __ ___________ _ \n" " \\ \\ / // ___| ___ \\ | | \n" " \\ V / \\ `--.| |_/ / ___ _ __ ___| |__ \n" " / \\ `--. \\ ___ \\/ _ \\ '_ \\ / __| '_ \\ \n" " / /^\\ \\/\\__/ / |_/ / __/ | | | (__| | | | \n" " \\/ \\/\\____/\\____/ \\___|_| |_|\\___|_| |_| \n\n" ); border_print(); center_print("Developed at Argonne National Laboratory", 79); char v[100]; sprintf(v, "Version: %d", version); center_print(v, 79); border_print(); } // Prints Section titles in center of 80 char terminal void center_print(const char *s, int width) { int length = strlen(s); int i; for (i=0; i<=(width-length)/2; i++) { fputs(" ", stdout); } fputs(s, stdout); fputs("\n", stdout); } void print_results( Inputs in, int mype, double runtime, int nprocs, unsigned long long vhash ) { // Calculate Lookups per sec int lookups_per_sec = (int) ((double) in.lookups / runtime); // If running in MPI, reduce timing statistics and calculate average #ifdef MPI int total_lookups = 0; MPI_Barrier(MPI_COMM_WORLD); MPI_Reduce(&lookups_per_sec, &total_lookups, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); #endif // Print output if( mype == 0 ) { border_print(); center_print("RESULTS", 79); border_print(); // Print the results printf("Threads: %d\n", in.nthreads); #ifdef MPI printf("MPI ranks: %d\n", nprocs); #endif #ifdef MPI printf("Total Lookups/s: "); fancy_int(total_lookups); printf("Avg Lookups/s per MPI rank: "); fancy_int(total_lookups / nprocs); #else printf("Runtime: %.3lf seconds\n", runtime); printf("Lookups: "); fancy_int(in.lookups); printf("Lookups/s: "); fancy_int(lookups_per_sec); #endif #ifdef VERIFICATION printf("Verification checksum: %llu\n", vhash); #endif border_print(); // For bechmarking, output lookup/s data to file if( SAVE ) { FILE * out = fopen( "results.txt", "a" ); fprintf(out, "%d\t%d\n", in.nthreads, lookups_per_sec); fclose(out); } } } void print_inputs(Inputs in, int nprocs, int version ) { // Calculate Estimate of Memory Usage int mem_tot = estimate_mem_usage( in ); logo(version); center_print("INPUT SUMMARY", 79); border_print(); #ifdef VERIFICATION printf("Verification Mode: on\n"); #endif printf("Materials: %d\n", 12); printf("H-M Benchmark Size: %s\n", in.HM); printf("Total Nuclides: %ld\n", in.n_isotopes); printf("Gridpoints (per Nuclide): "); fancy_int(in.n_gridpoints); printf("Unionized Energy Gridpoints: "); fancy_int(in.n_isotopes*in.n_gridpoints); printf("XS Lookups: "); fancy_int(in.lookups); #ifdef MPI printf("MPI Ranks: %d\n", nprocs); printf("OMP Threads per MPI Rank: %d\n", in.nthreads); printf("Mem Usage per MPI Rank (MB): "); fancy_int(mem_tot); #else printf("Threads: %d\n", in.nthreads); printf("Est. Memory Usage (MB): "); fancy_int(mem_tot); #endif border_print(); center_print("INITIALIZATION", 79); border_print(); } void border_print(void) { printf( "===================================================================" "=============\n"); } // Prints comma separated integers - for ease of reading void fancy_int( long a ) { if( a < 1000 ) printf("%ld\n",a); else if( a >= 1000 && a < 1000000 ) printf("%ld,%03ld\n", a / 1000, a % 1000); else if( a >= 1000000 && a < 1000000000 ) printf("%ld,%03ld,%03ld\n",a / 1000000,(a % 1000000) / 1000,a % 1000 ); else if( a >= 1000000000 ) printf("%ld,%03ld,%03ld,%03ld\n", a / 1000000000, (a % 1000000000) / 1000000, (a % 1000000) / 1000, a % 1000 ); else printf("%ld\n",a); } void print_CLI_error(void) { printf("Usage: ./XSBench \n"); printf("Options include:\n"); printf(" -t Number of OpenMP threads to run\n"); printf(" -s Size of H-M Benchmark to run (small, large, XL, XXL)\n"); printf(" -g Number of gridpoints per nuclide (overrides -s defaults)\n"); printf(" -l Number of Cross-section (XS) lookups\n"); printf("Default is equivalent to: -s large -l 15000000\n"); printf("See readme for full description of default run values\n"); exit(4); } Inputs read_CLI( int argc, char * argv[] ) { Inputs input; // defaults to max threads on the system input.nthreads = omp_get_num_procs(); // defaults to 355 (corresponding to H-M Large benchmark) input.n_isotopes = 355; // defaults to 11303 (corresponding to H-M Large benchmark) input.n_gridpoints = 11303; // defaults to 15,000,000 input.lookups = 15000000; // defaults to H-M Large benchmark input.HM = (char *) malloc( 6 * sizeof(char) ); input.HM[0] = 'l' ; input.HM[1] = 'a' ; input.HM[2] = 'r' ; input.HM[3] = 'g' ; input.HM[4] = 'e' ; input.HM[5] = '\0'; // Check if user sets these int user_g = 0; // Collect Raw Input for( int i = 1; i < argc; i++ ) { char * arg = argv[i]; // nthreads (-t) if( strcmp(arg, "-t") == 0 ) { if( ++i < argc ) input.nthreads = atoi(argv[i]); else print_CLI_error(); } // n_gridpoints (-g) else if( strcmp(arg, "-g") == 0 ) { if( ++i < argc ) { user_g = 1; input.n_gridpoints = atol(argv[i]); } else print_CLI_error(); } // lookups (-l) else if( strcmp(arg, "-l") == 0 ) { if( ++i < argc ) input.lookups = atoi(argv[i]); else print_CLI_error(); } // HM (-s) else if( strcmp(arg, "-s") == 0 ) { if( ++i < argc ) input.HM = argv[i]; else print_CLI_error(); } else print_CLI_error(); } // Validate Input // Validate nthreads if( input.nthreads < 1 ) print_CLI_error(); // Validate n_isotopes if( input.n_isotopes < 1 ) print_CLI_error(); // Validate n_gridpoints if( input.n_gridpoints < 1 ) print_CLI_error(); // Validate lookups if( input.lookups < 1 ) print_CLI_error(); // Validate HM size if( strcasecmp(input.HM, "small") != 0 && strcasecmp(input.HM, "large") != 0 && strcasecmp(input.HM, "XL") != 0 && strcasecmp(input.HM, "XXL") != 0 ) print_CLI_error(); // Set HM size specific parameters // (defaults to large) if( strcasecmp(input.HM, "small") == 0 ) input.n_isotopes = 68; else if( strcasecmp(input.HM, "XL") == 0 && user_g == 0 ) input.n_gridpoints = 238847; // sized to make 120 GB XS data else if( strcasecmp(input.HM, "XXL") == 0 && user_g == 0 ) input.n_gridpoints = 238847 * 2.1; // 252 GB XS data // Return input struct return input; }