diff options
Diffstat (limited to 'src/Experiment.cpp')
-rw-r--r-- | src/Experiment.cpp | 1068 |
1 files changed, 581 insertions, 487 deletions
diff --git a/src/Experiment.cpp b/src/Experiment.cpp index 27e1a25..e58be0a 100644 --- a/src/Experiment.cpp +++ b/src/Experiment.cpp @@ -35,7 +35,7 @@ Experiment::Experiment() : pages_per_chain (DEFAULT_PAGES_PER_CHAIN), chains_per_thread(DEFAULT_CHAINS_PER_THREAD), bytes_per_thread (DEFAULT_BYTES_PER_THREAD), - num_threads (DEFAULT_THREADS), + num_threads (DEFAULT_THREADS), bytes_per_test (DEFAULT_BYTES_PER_TEST), busy_cycles (DEFAULT_BUSY_CYCLES), seconds (DEFAULT_SECONDS), @@ -55,233 +55,334 @@ Experiment::Experiment() : { } -Experiment::~Experiment() -{ +Experiment::~Experiment() { } - // interface: - // - // -l or --line bytes per cache line (line size) - // -p or --page bytes per page (page size) - // -c or --chain bytes per chain (used to compute pages per chain) - // -r or --references chains per thread (memory loading) - // -t or --threads number of threads (concurrency and contention) - // -i or --iters iterations - // -e or --experiments experiments - // -b or --busy amount of cycles processor should remain busy - // -f or --prefetch prefetch data - // -a or --access memory access pattern - // random random access pattern - // forward <stride> exclusive OR and mask - // reverse <stride> addition and offset - // -o or --output output mode - // hdr header only - // csv csv only - // both header + csv - // table human-readable table of values - // -n or --numa numa placement - // local local allocation of all chains - // xor <mask> exclusive OR and mask - // add <offset> addition and offset - // map <map> explicit mapping of threads and chains to domains - -int -Experiment::parse_args(int argc, char* argv[]) -{ - int error = 0; - for (int i=1; i < argc; i++) { - if (strcasecmp(argv[i], "-x") == 0 || strcasecmp(argv[i], "--strict") == 0) { - this->strict = 1; - } else if (strcasecmp(argv[i], "-s") == 0 || strcasecmp(argv[i], "--seconds") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->seconds = Experiment::parse_real(argv[i]); - this->iterations = 0; - if (this->seconds == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-l") == 0 || strcasecmp(argv[i], "--line") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->bytes_per_line = Experiment::parse_number(argv[i]); - if (this->bytes_per_line == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-p") == 0 || strcasecmp(argv[i], "--page") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->bytes_per_page = Experiment::parse_number(argv[i]); - if (this->bytes_per_page == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-c") == 0 || strcasecmp(argv[i], "--chain") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->bytes_per_chain = Experiment::parse_number(argv[i]); - if (this->bytes_per_chain == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-r") == 0 || strcasecmp(argv[i], "--references") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->chains_per_thread = Experiment::parse_number(argv[i]); - if (this->chains_per_thread == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-t") == 0 || strcasecmp(argv[i], "--threads") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->num_threads = Experiment::parse_number(argv[i]); - if (this->num_threads == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-i") == 0 || strcasecmp(argv[i], "--iterations") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->iterations = Experiment::parse_number(argv[i]); - this->seconds = 0; - if (this->iterations == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-e") == 0 || strcasecmp(argv[i], "--experiments") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->experiments = Experiment::parse_number(argv[i]); - if (this->experiments == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-b") == 0 || strcasecmp(argv[i], "--busy") == 0) { - i++; - if (i == argc) { error = 1; break; } - this->busy_cycles = Experiment::parse_number(argv[i]); - if (this->experiments == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "-f") == 0 || strcasecmp(argv[i], "--prefetch") == 0) { - this->prefetch = true; - } else if (strcasecmp(argv[i], "-a") == 0 || strcasecmp(argv[i], "--access") == 0) { - i++; - if (i == argc) { error = 1; break; } - if (strcasecmp(argv[i], "random") == 0) { - this->access_pattern = RANDOM; - } else if (strcasecmp(argv[i], "forward") == 0) { - this->access_pattern = STRIDED; - i++; - if (i == argc) { error = 1; break; } - this->stride = Experiment::parse_number(argv[i]); - if (this->stride == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "reverse") == 0) { - this->access_pattern = STRIDED; - i++; - if (i == argc) { error = 1; break; } - this->stride = - Experiment::parse_number(argv[i]); - if (this->stride == 0) { error = 1; break; } - } else if (strcasecmp(argv[i], "stream") == 0) { - this->access_pattern = STREAM; - i++; - if (i == argc) { error = 1; break; } - this->stride = Experiment::parse_number(argv[i]); - if (this->stride == 0) { error = 1; break; } - } else { - error = 1; - break; - } - } else if (strcasecmp(argv[i], "-o") == 0 || strcasecmp(argv[i], "--output") == 0) { - i++; - if (i == argc) { error = 1; break; } - if (strcasecmp(argv[i], "table") == 0) { - this->output_mode = TABLE; - } else if (strcasecmp(argv[i], "csv") == 0) { - this->output_mode = CSV; - } else if (strcasecmp(argv[i], "both") == 0) { - this->output_mode = BOTH; - } else if (strcasecmp(argv[i], "hdr") == 0) { - this->output_mode = HEADER; - } else if (strcasecmp(argv[i], "header") == 0) { - this->output_mode = HEADER; - } else { - error = 1; - break; - } - } else if (strcasecmp(argv[i], "-n") == 0 || strcasecmp(argv[i], "--numa") == 0) { - i++; - if (i == argc) { error = 1; break; } - if (strcasecmp(argv[i], "local") == 0) { - this->numa_placement = LOCAL; - } else if (strcasecmp(argv[i], "xor") == 0) { - this->numa_placement = XOR; - i++; - if (i == argc) { error = 1; break; } - this->offset_or_mask = Experiment::parse_number(argv[i]); - } else if (strcasecmp(argv[i], "add") == 0) { - this->numa_placement = ADD; - i++; - if (i == argc) { error = 1; break; } - this->offset_or_mask = Experiment::parse_number(argv[i]); - } else if (strcasecmp(argv[i], "map") == 0) { - this->numa_placement = MAP; - i++; - if (i == argc) { error = 1; break; } - this->placement_map = argv[i]; - } else { - error = 1; - break; - } - } else { - error = 1; - break; +// interface: +// +// -l or --line bytes per cache line (line size) +// -p or --page bytes per page (page size) +// -c or --chain bytes per chain (used to compute pages per chain) +// -r or --references chains per thread (memory loading) +// -t or --threads number of threads (concurrency and contention) +// -i or --iters iterations +// -e or --experiments experiments +// -b or --busy amount of cycles processor should remain busy +// -f or --prefetch prefetch data +// -a or --access memory access pattern +// random random access pattern +// forward <stride> exclusive OR and mask +// reverse <stride> addition and offset +// -o or --output output mode +// hdr header only +// csv csv only +// both header + csv +// table human-readable table of values +// -n or --numa numa placement +// local local allocation of all chains +// xor <mask> exclusive OR and mask +// add <offset> addition and offset +// map <map> explicit mapping of threads and chains to domains + +int Experiment::parse_args(int argc, char* argv[]) { + int error = 0; + for (int i = 1; i < argc; i++) { + if (strcasecmp(argv[i], "-x") == 0 + || strcasecmp(argv[i], "--strict") == 0) { + this->strict = 1; + } else if (strcasecmp(argv[i], "-s") == 0 + || strcasecmp(argv[i], "--seconds") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->seconds = Experiment::parse_real(argv[i]); + this->iterations = 0; + if (this->seconds == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-l") == 0 + || strcasecmp(argv[i], "--line") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->bytes_per_line = Experiment::parse_number(argv[i]); + if (this->bytes_per_line == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-p") == 0 + || strcasecmp(argv[i], "--page") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->bytes_per_page = Experiment::parse_number(argv[i]); + if (this->bytes_per_page == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-c") == 0 + || strcasecmp(argv[i], "--chain") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->bytes_per_chain = Experiment::parse_number(argv[i]); + if (this->bytes_per_chain == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-r") == 0 + || strcasecmp(argv[i], "--references") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->chains_per_thread = Experiment::parse_number(argv[i]); + if (this->chains_per_thread == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-t") == 0 + || strcasecmp(argv[i], "--threads") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->num_threads = Experiment::parse_number(argv[i]); + if (this->num_threads == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-i") == 0 + || strcasecmp(argv[i], "--iterations") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->iterations = Experiment::parse_number(argv[i]); + this->seconds = 0; + if (this->iterations == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-e") == 0 + || strcasecmp(argv[i], "--experiments") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->experiments = Experiment::parse_number(argv[i]); + if (this->experiments == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-b") == 0 + || strcasecmp(argv[i], "--busy") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + this->busy_cycles = Experiment::parse_number(argv[i]); + if (this->experiments == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-f") == 0 + || strcasecmp(argv[i], "--prefetch") == 0) { + this->prefetch = true; + } else if (strcasecmp(argv[i], "-a") == 0 + || strcasecmp(argv[i], "--access") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + if (strcasecmp(argv[i], "random") == 0) { + this->access_pattern = RANDOM; + } else if (strcasecmp(argv[i], "forward") == 0) { + this->access_pattern = STRIDED; + i++; + if (i == argc) { + error = 1; + break; + } + this->stride = Experiment::parse_number(argv[i]); + if (this->stride == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "reverse") == 0) { + this->access_pattern = STRIDED; + i++; + if (i == argc) { + error = 1; + break; + } + this->stride = -Experiment::parse_number(argv[i]); + if (this->stride == 0) { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "stream") == 0) { + this->access_pattern = STREAM; + i++; + if (i == argc) { + error = 1; + break; + } + this->stride = Experiment::parse_number(argv[i]); + if (this->stride == 0) { + error = 1; + break; + } + } else { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-o") == 0 + || strcasecmp(argv[i], "--output") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + if (strcasecmp(argv[i], "table") == 0) { + this->output_mode = TABLE; + } else if (strcasecmp(argv[i], "csv") == 0) { + this->output_mode = CSV; + } else if (strcasecmp(argv[i], "both") == 0) { + this->output_mode = BOTH; + } else if (strcasecmp(argv[i], "hdr") == 0) { + this->output_mode = HEADER; + } else if (strcasecmp(argv[i], "header") == 0) { + this->output_mode = HEADER; + } else { + error = 1; + break; + } + } else if (strcasecmp(argv[i], "-n") == 0 + || strcasecmp(argv[i], "--numa") == 0) { + i++; + if (i == argc) { + error = 1; + break; + } + if (strcasecmp(argv[i], "local") == 0) { + this->numa_placement = LOCAL; + } else if (strcasecmp(argv[i], "xor") == 0) { + this->numa_placement = XOR; + i++; + if (i == argc) { + error = 1; + break; + } + this->offset_or_mask = Experiment::parse_number(argv[i]); + } else if (strcasecmp(argv[i], "add") == 0) { + this->numa_placement = ADD; + i++; + if (i == argc) { + error = 1; + break; + } + this->offset_or_mask = Experiment::parse_number(argv[i]); + } else if (strcasecmp(argv[i], "map") == 0) { + this->numa_placement = MAP; + i++; + if (i == argc) { + error = 1; + break; + } + this->placement_map = argv[i]; + } else { + error = 1; + break; + } + } else { + error = 1; + break; + } + } + + + // if we've hit an error, print a message and quit + if (error) { + printf("usage: %s <options>\n", argv[0]); + printf("where <options> are selected from the following:\n"); + printf(" [-h|--help] # this message\n"); + printf(" [-l|--line] <number> # bytes per cache line (cache line size)\n"); + printf(" [-p|--page] <number> # bytes per page (page size)\n"); + printf(" [-c|--chain] <number> # bytes per chain (used to compute pages per chain)\n"); + printf(" [-r|--references] <number> # chains per thread (memory loading)\n"); + printf(" [-t|--threads] <number> # number of threads (concurrency and contention)\n"); + printf(" [-i|--iterations] <number> # iterations per experiment\n"); + printf(" [-e|--experiments] <number> # experiments\n"); + printf(" [-a|--access] <pattern> # memory access pattern\n"); + printf(" [-o|--output] <format> # output format\n"); + printf(" [-n|--numa] <placement> # numa placement\n"); + printf(" [-s|--seconds] <number> # run each experiment for <number> seconds\n"); + printf(" [-b|--busy] <number> # how much processing cycles each loop should count\n"); + printf(" [-f|--prefetch] # prefetch data\n"); + printf(" [-x|--strict] # fail rather than adjust options to sensible values\n"); + printf("\n"); + printf("<pattern> is selected from the following:\n"); + printf(" random # all chains are accessed randomly\n"); + printf(" forward <stride> # chains are in forward order with constant stride\n"); + printf(" reverse <stride> # chains are in reverse order with constant stride\n"); + printf(" stream <stride> # references are calculated rather than read from memory\n"); + printf("\n"); + printf("Note: <stride> is always a small positive integer.\n"); + printf("\n"); + printf("<format> is selected from the following:\n"); + printf(" hdr # csv header only\n"); + printf(" csv # results in csv format only\n"); + printf(" both # header and results in csv format\n"); + printf(" table # human-readable table of values\n"); + printf("\n"); + printf("<placement> is selected from the following:\n"); + printf(" local # all chains are allocated locally\n"); + printf(" xor <mask> # exclusive OR and mask\n"); + printf(" add <offset> # addition and offset\n"); + printf(" map <map> # explicit mapping of threads and chains to domains\n"); + printf("\n"); + printf("<map> has the form \"t1:c11,c12,...,c1m;t2:c21,...,c2m;...;tn:cn1,...,cnm\"\n"); + printf("where t[i] is the NUMA domain where the ith thread is run,\n"); + printf("and c[i][j] is the NUMA domain where the jth chain in the ith thread is allocated.\n"); + printf("(The values t[i] and c[i][j] must all be zero or small positive integers.)\n"); + printf("\n"); + printf("Note: for maps, each thread must have the same number of chains,\n"); + printf("maps override the -t or --threads specification,\n"); + printf("NUMA domains are whole numbers in the range of 0..N, and\n"); + printf("thread or chain domains that exceed the maximum NUMA domain\n"); + printf("are wrapped around using a MOD function.\n"); + printf("\n"); + printf("To determine the number of NUMA domains currently available\n"); + printf("on your system, use a command such as \"numastat\".\n"); + printf("\n"); + printf("Final note: strict is not yet fully implemented, and\n"); + printf("maps do not gracefully handle ill-formed map specifications.\n"); + + return 1; } - } - - - // if we've hit an error, print a message and quit - if (error) { - printf("usage: %s <options>\n", argv[0]); - printf("where <options> are selected from the following:\n"); - printf(" [-h|--help] # this message\n"); - printf(" [-l|--line] <number> # bytes per cache line (cache line size)\n"); - printf(" [-p|--page] <number> # bytes per page (page size)\n"); - printf(" [-c|--chain] <number> # bytes per chain (used to compute pages per chain)\n"); - printf(" [-r|--references] <number> # chains per thread (memory loading)\n"); - printf(" [-t|--threads] <number> # number of threads (concurrency and contention)\n"); - printf(" [-i|--iterations] <number> # iterations per experiment\n"); - printf(" [-e|--experiments] <number> # experiments\n"); - printf(" [-a|--access] <pattern> # memory access pattern\n"); - printf(" [-o|--output] <format> # output format\n"); - printf(" [-n|--numa] <placement> # numa placement\n"); - printf(" [-s|--seconds] <number> # run each experiment for <number> seconds\n"); - printf(" [-b|--busy] <number> # how much processing cycles each loop should count\n"); - printf(" [-f|--prefetch] # prefetch data\n"); - printf(" [-x|--strict] # fail rather than adjust options to sensible values\n"); - printf("\n"); - printf("<pattern> is selected from the following:\n"); - printf(" random # all chains are accessed randomly\n"); - printf(" forward <stride> # chains are in forward order with constant stride\n"); - printf(" reverse <stride> # chains are in reverse order with constant stride\n"); - printf(" stream <stride> # references are calculated rather than read from memory\n"); - printf("\n"); - printf("Note: <stride> is always a small positive integer.\n"); - printf("\n"); - printf("<format> is selected from the following:\n"); - printf(" hdr # csv header only\n"); - printf(" csv # results in csv format only\n"); - printf(" both # header and results in csv format\n"); - printf(" table # human-readable table of values\n"); - printf("\n"); - printf("<placement> is selected from the following:\n"); - printf(" local # all chains are allocated locally\n"); - printf(" xor <mask> # exclusive OR and mask\n"); - printf(" add <offset> # addition and offset\n"); - printf(" map <map> # explicit mapping of threads and chains to domains\n"); - printf("\n"); - printf("<map> has the form \"t1:c11,c12,...,c1m;t2:c21,...,c2m;...;tn:cn1,...,cnm\"\n"); - printf("where t[i] is the NUMA domain where the ith thread is run,\n"); - printf("and c[i][j] is the NUMA domain where the jth chain in the ith thread is allocated.\n"); - printf("(The values t[i] and c[i][j] must all be zero or small positive integers.)\n"); - printf("\n"); - printf("Note: for maps, each thread must have the same number of chains,\n"); - printf("maps override the -t or --threads specification,\n"); - printf("NUMA domains are whole numbers in the range of 0..N, and\n"); - printf("thread or chain domains that exceed the maximum NUMA domain\n"); - printf("are wrapped around using a MOD function.\n"); - printf("\n"); - printf("To determine the number of NUMA domains currently available\n"); - printf("on your system, use a command such as \"numastat\".\n"); - printf("\n"); - printf("Final note: strict is not yet fully implemented, and\n"); - printf("maps do not gracefully handle ill-formed map specifications.\n"); - - return 1; - } - - - // STRICT -- fail if specifications are inconsistent - - // compute lines per page and lines per chain - // based on input and defaults. - // we round up page and chain sizes when needed. + + + // STRICT -- fail if specifications are inconsistent + + // compute lines per page and lines per chain + // based on input and defaults. + // we round up page and chain sizes when needed. this->lines_per_page = (this->bytes_per_page+this->bytes_per_line-1) / this->bytes_per_line; this->bytes_per_page = this->bytes_per_line * this->lines_per_page; this->pages_per_chain = (this->bytes_per_chain+this->bytes_per_page-1) / this->bytes_per_page; @@ -294,314 +395,307 @@ Experiment::parse_args(int argc, char* argv[]) this->links_per_chain = this->lines_per_chain * this->links_per_line; - // allocate the chain roots for all threads - // and compute the chain locations - // (the chains themselves are initialized by the threads) - switch (this->numa_placement) { - case LOCAL : - case XOR : - case ADD : - this->thread_domain = new int32 [ this->num_threads ]; - this->chain_domain = new int32*[ this->num_threads ]; - this->random_state = new char* [ this->num_threads ]; - - for (int i=0; i < this->num_threads; i++) { - this->chain_domain[i] = new int32 [ this->chains_per_thread ]; - - const int state_size = 256; - this->random_state[i] = new char[state_size]; - initstate((unsigned int) i, (char *) this->random_state[i], (size_t) state_size); + // allocate the chain roots for all threads + // and compute the chain locations + // (the chains themselves are initialized by the threads) + switch (this->numa_placement) { + case LOCAL: + case XOR: + case ADD: + this->thread_domain = new int32[this->num_threads]; + this->chain_domain = new int32*[this->num_threads]; + this->random_state = new char*[this->num_threads]; + + for (int i = 0; i < this->num_threads; i++) { + this->chain_domain[i] = new int32[this->chains_per_thread]; + + const int state_size = 256; + this->random_state[i] = new char[state_size]; + initstate((unsigned int) i, (char *) this->random_state[i], + (size_t) state_size); + } + break; } - break; - } - #if defined(NUMA) - this->numa_max_domain = numa_max_node(); - this->num_numa_domains = this->numa_max_domain + 1; + this->numa_max_domain = numa_max_node(); + this->num_numa_domains = this->numa_max_domain + 1; #endif + switch (this->numa_placement) { + case LOCAL: + default: + this->alloc_local(); + break; + case XOR: + this->alloc_xor(); + break; + case ADD: + this->alloc_add(); + break; + case MAP: + this->alloc_map(); + break; + } - switch (this->numa_placement) { - case LOCAL : - default: - this->alloc_local(); - break; - case XOR : - this->alloc_xor(); - break; - case ADD : - this->alloc_add(); - break; - case MAP : - this->alloc_map(); - break; - } - - return 0; + return 0; } - -int64 -Experiment::parse_number( const char* s ) -{ - int64 result = 0; - - int len = strlen( s ); - for (int i=0; i < len; i++) { - if ( '0' <= s[i] && s[i] <= '9' ) { - result = result * 10 + s[i] - '0'; - } else if (s[i] == 'k' || s[i] == 'K') { - result = result << 10; - break; - } else if (s[i] == 'm' || s[i] == 'M') { - result = result << 20; - break; - } else if (s[i] == 'g' || s[i] == 'G') { - result = result << 30; - break; - } else if (s[i] == 't' || s[i] == 'T') { - result = result << 40; - break; - } else { - break; +int64 Experiment::parse_number(const char* s) { + int64 result = 0; + + int len = strlen(s); + for (int i = 0; i < len; i++) { + if ('0' <= s[i] && s[i] <= '9') { + result = result * 10 + s[i] - '0'; + } else if (s[i] == 'k' || s[i] == 'K') { + result = result << 10; + break; + } else if (s[i] == 'm' || s[i] == 'M') { + result = result << 20; + break; + } else if (s[i] == 'g' || s[i] == 'G') { + result = result << 30; + break; + } else if (s[i] == 't' || s[i] == 'T') { + result = result << 40; + break; + } else { + break; + } } - } - return result; + return result; } - -float -Experiment::parse_real( const char* s ) -{ - float result = 0; - bool decimal = false; - float power = 1; - - int len = strlen( s ); - for (int i=0; i < len; i++) { - if ( '0' <= s[i] && s[i] <= '9' ) { - if (! decimal) { - result = result * 10 + s[i] - '0'; - } else { - power = power / 10; - result = result + (s[i] - '0') * power; - } - } else if ( '.' == s[i] ) { - decimal = true; - } else { - break; +float Experiment::parse_real(const char* s) { + float result = 0; + bool decimal = false; + float power = 1; + + int len = strlen(s); + for (int i = 0; i < len; i++) { + if ('0' <= s[i] && s[i] <= '9') { + if (!decimal) { + result = result * 10 + s[i] - '0'; + } else { + power = power / 10; + result = result + (s[i] - '0') * power; + } + } else if ('.' == s[i]) { + decimal = true; + } else { + break; + } } - } - return result; + return result; } -void -Experiment::alloc_local() -{ - for (int i=0; i < this->num_threads; i++) { - this->thread_domain[i] = i % this->num_numa_domains; - for (int j=0; j < this->chains_per_thread; j++) { - this->chain_domain[i][j] = this->thread_domain[i]; +void Experiment::alloc_local() { + for (int i = 0; i < this->num_threads; i++) { + this->thread_domain[i] = i % this->num_numa_domains; + for (int j = 0; j < this->chains_per_thread; j++) { + this->chain_domain[i][j] = this->thread_domain[i]; + } } - } } -void -Experiment::alloc_xor() -{ - for (int i=0; i < this->num_threads; i++) { - this->thread_domain[i] = i % this->num_numa_domains; - for (int j=0; j < this->chains_per_thread; j++) { - this->chain_domain[i][j] = (this->thread_domain[i] ^ this->offset_or_mask) % this->num_numa_domains; +void Experiment::alloc_xor() { + for (int i = 0; i < this->num_threads; i++) { + this->thread_domain[i] = i % this->num_numa_domains; + for (int j = 0; j < this->chains_per_thread; j++) { + this->chain_domain[i][j] = (this->thread_domain[i] + ^ this->offset_or_mask) % this->num_numa_domains; + } } - } } -void -Experiment::alloc_add() -{ - for (int i=0; i < this->num_threads; i++) { - this->thread_domain[i] = i % this->num_numa_domains; - for (int j=0; j < this->chains_per_thread; j++) { - this->chain_domain[i][j] = (this->thread_domain[i] + this->offset_or_mask) % this->num_numa_domains; +void Experiment::alloc_add() { + for (int i = 0; i < this->num_threads; i++) { + this->thread_domain[i] = i % this->num_numa_domains; + for (int j = 0; j < this->chains_per_thread; j++) { + this->chain_domain[i][j] = (this->thread_domain[i] + + this->offset_or_mask) % this->num_numa_domains; + } } - } } - // DOES NOT HANDLE ILL-FORMED SPECIFICATIONS -void -Experiment::alloc_map() -{ - // STRICT -- fail if specifications are inconsistent - - // maps look like "t1:c11,c12,...,c1m;t2:c21,...,c2m;...;tn:cn1,...,cnm" - // where t[i] is the thread domain of the ith thread, - // and c[i][j] is the chain domain of the jth chain in the ith thread - - // count the thread descriptors by counting ";" up to EOS - int threads = 1; - char *p = this->placement_map; - while (*p != '\0') { - if (*p == ';') threads += 1; - p++; - } - int thread_domain[ threads ]; - - // count the chain descriptors by counting "," up to ";" or EOS - int chains = 1; - p = this->placement_map; - while (*p != '\0') { - if (*p == ';') break; - if (*p == ',') chains += 1; - p++; - } - int chain_domain [ threads ][ chains ]; - - int t=0, c=0; - p = this->placement_map; - while (*p != '\0') { - // everything up to ":" is the thread domain - int i = 0; - char buf[64]; +// DOES NOT HANDLE ILL-FORMED SPECIFICATIONS +void Experiment::alloc_map() { + // STRICT -- fail if specifications are inconsistent + + // maps look like "t1:c11,c12,...,c1m;t2:c21,...,c2m;...;tn:cn1,...,cnm" + // where t[i] is the thread domain of the ith thread, + // and c[i][j] is the chain domain of the jth chain in the ith thread + + // count the thread descriptors by counting ";" up to EOS + int threads = 1; + char *p = this->placement_map; while (*p != '\0') { - if (*p == ':') { p++; break; } - buf[i] = *p; - i++; - p++; + if (*p == ';') + threads += 1; + p++; } - buf[i] = '\0'; - thread_domain[t] = Experiment::parse_number(buf); + int thread_domain[threads]; - // search for one or several ',' - c = 0; - while (*p != '\0' && *p != ';') { - if (chains <= c || threads <= t) { - // error in the thread/chain specification - fprintf(stderr, "Malformed map.\n"); - exit(1); - } - int i = 0; - while (*p != '\0' && *p != ';') { - if (*p == ',') { p++; break; } - buf[i] = *p; - i++; + // count the chain descriptors by counting "," up to ";" or EOS + int chains = 1; + p = this->placement_map; + while (*p != '\0') { + if (*p == ';') + break; + if (*p == ',') + chains += 1; p++; - } - buf[i] = '\0'; - chain_domain[t][c] = Experiment::parse_number(buf); - c++; } + int chain_domain[threads][chains]; - if (*p == '\0') break; - if (*p == ';') p++; - t++; - } - + int t = 0, c = 0; + p = this->placement_map; + while (*p != '\0') { + // everything up to ":" is the thread domain + int i = 0; + char buf[64]; + while (*p != '\0') { + if (*p == ':') { + p++; + break; + } + buf[i] = *p; + i++; + p++; + } + buf[i] = '\0'; + thread_domain[t] = Experiment::parse_number(buf); + + // search for one or several ',' + c = 0; + while (*p != '\0' && *p != ';') { + if (chains <= c || threads <= t) { + // error in the thread/chain specification + fprintf(stderr, "Malformed map.\n"); + exit(1); + } + int i = 0; + while (*p != '\0' && *p != ';') { + if (*p == ',') { + p++; + break; + } + buf[i] = *p; + i++; + p++; + } + buf[i] = '\0'; + chain_domain[t][c] = Experiment::parse_number(buf); + c++; + } + + if (*p == '\0') + break; + if (*p == ';') + p++; + t++; + } - this->num_threads = threads; - this->chains_per_thread = chains; + this->num_threads = threads; + this->chains_per_thread = chains; - this->thread_domain = new int32 [ this->num_threads ]; - this->chain_domain = new int32*[ this->num_threads ]; - this->random_state = new char* [ this->num_threads ]; + this->thread_domain = new int32[this->num_threads]; + this->chain_domain = new int32*[this->num_threads]; + this->random_state = new char*[this->num_threads]; - for (int i=0; i < this->num_threads; i++) { - this->thread_domain[i] = thread_domain[i] % this->num_numa_domains; + for (int i = 0; i < this->num_threads; i++) { + this->thread_domain[i] = thread_domain[i] % this->num_numa_domains; - const int state_size = 256; - this->random_state[i] = new char[state_size]; - initstate((unsigned int) i, (char *) this->random_state[i], (size_t) state_size); + const int state_size = 256; + this->random_state[i] = new char[state_size]; + initstate((unsigned int) i, (char *) this->random_state[i], + (size_t) state_size); - this->chain_domain[i] = new int32 [ this->chains_per_thread ]; - for (int j=0; j < this->chains_per_thread; j++) { - this->chain_domain[i][j] = chain_domain[i][j] % this->num_numa_domains; + this->chain_domain[i] = new int32[this->chains_per_thread]; + for (int j = 0; j < this->chains_per_thread; j++) { + this->chain_domain[i][j] = chain_domain[i][j] + % this->num_numa_domains; + } } - } - this->bytes_per_thread = this->bytes_per_chain * this->chains_per_thread; - this->bytes_per_test = this->bytes_per_thread * this->num_threads; + this->bytes_per_thread = this->bytes_per_chain * this->chains_per_thread; + this->bytes_per_test = this->bytes_per_thread * this->num_threads; } #include "Chain.h" -void -Experiment::print() -{ - printf("strict = %d\n", strict); - printf("pointer_size = %d\n", pointer_size); - printf("sizeof(Chain) = %d\n", sizeof(Chain)); - printf("sizeof(Chain *) = %d\n", sizeof(Chain *)); - printf("bytes_per_line = %d\n", bytes_per_line); - printf("links_per_line = %d\n", links_per_line); - printf("bytes_per_page = %d\n", bytes_per_page); - printf("lines_per_page = %d\n", lines_per_page); - printf("links_per_page = %d\n", links_per_page); - printf("bytes_per_chain = %d\n", bytes_per_chain); - printf("lines_per_chain = %d\n", lines_per_chain); - printf("links_per_chain = %d\n", links_per_chain); - printf("pages_per_chain = %d\n", pages_per_chain); - printf("chains_per_thread = %d\n", chains_per_thread); - printf("bytes_per_thread = %d\n", bytes_per_thread); - printf("num_threads = %d\n", num_threads); - printf("bytes_per_test = %d\n", bytes_per_test); - printf("busy cycles = %d\n", busy_cycles); - printf("prefetch = %d\n", prefetch); - printf("iterations = %d\n", iterations); - printf("experiments = %d\n", experiments); - printf("access_pattern = %d\n", access_pattern); - printf("stride = %d\n", stride); - printf("output_mode = %d\n", output_mode); - printf("numa_placement = %d\n", numa_placement); - printf("offset_or_mask = %d\n", offset_or_mask); - printf("numa_max_domain = %d\n", numa_max_domain); - printf("num_numa_domains = %d\n", num_numa_domains); - - for (int i=0; i < this->num_threads; i++) { - printf("%d: ", this->thread_domain[i]); - for (int j=0; j < this->chains_per_thread; j++) { - printf("%d,", this->chain_domain[i][j]); +void Experiment::print() { + printf("strict = %d\n", strict); + printf("pointer_size = %d\n", pointer_size); + printf("sizeof(Chain) = %d\n", sizeof(Chain)); + printf("sizeof(Chain *) = %d\n", sizeof(Chain *)); + printf("bytes_per_line = %d\n", bytes_per_line); + printf("links_per_line = %d\n", links_per_line); + printf("bytes_per_page = %d\n", bytes_per_page); + printf("lines_per_page = %d\n", lines_per_page); + printf("links_per_page = %d\n", links_per_page); + printf("bytes_per_chain = %d\n", bytes_per_chain); + printf("lines_per_chain = %d\n", lines_per_chain); + printf("links_per_chain = %d\n", links_per_chain); + printf("pages_per_chain = %d\n", pages_per_chain); + printf("chains_per_thread = %d\n", chains_per_thread); + printf("bytes_per_thread = %d\n", bytes_per_thread); + printf("num_threads = %d\n", num_threads); + printf("bytes_per_test = %d\n", bytes_per_test); + printf("busy cycles = %d\n", busy_cycles); + printf("prefetch = %d\n", prefetch); + printf("iterations = %d\n", iterations); + printf("experiments = %d\n", experiments); + printf("access_pattern = %d\n", access_pattern); + printf("stride = %d\n", stride); + printf("output_mode = %d\n", output_mode); + printf("numa_placement = %d\n", numa_placement); + printf("offset_or_mask = %d\n", offset_or_mask); + printf("numa_max_domain = %d\n", numa_max_domain); + printf("num_numa_domains = %d\n", num_numa_domains); + + for (int i = 0; i < this->num_threads; i++) { + printf("%d: ", this->thread_domain[i]); + for (int j = 0; j < this->chains_per_thread; j++) { + printf("%d,", this->chain_domain[i][j]); + } + printf("\n"); } - printf("\n"); - } - fflush(stdout); + fflush(stdout); } -const char* -Experiment::access() -{ - const char* result = NULL; - - if (this->access_pattern == RANDOM) { - result = "random"; - } else if (this->access_pattern == STRIDED && 0 < this->stride) { - result = "forward"; - } else if (this->access_pattern == STRIDED && this->stride < 0) { - result = "reverse"; - } else if (this->access_pattern == STREAM) { - result = "stream"; - } - - return result; +const char* Experiment::access() { + const char* result = NULL; + + if (this->access_pattern == RANDOM) { + result = "random"; + } else if (this->access_pattern == STRIDED && 0 < this->stride) { + result = "forward"; + } else if (this->access_pattern == STRIDED && this->stride < 0) { + result = "reverse"; + } else if (this->access_pattern == STREAM) { + result = "stream"; + } + + return result; } -const char* -Experiment::placement() -{ - const char* result = NULL; - - if (this->numa_placement == LOCAL) { - result = "local"; - } else if (this->numa_placement == XOR) { - result = "xor"; - } else if (this->numa_placement == ADD) { - result = "add"; - } else if (this->numa_placement == MAP) { - result = "map"; - } - - return result; +const char* Experiment::placement() { + const char* result = NULL; + + if (this->numa_placement == LOCAL) { + result = "local"; + } else if (this->numa_placement == XOR) { + result = "xor"; + } else if (this->numa_placement == ADD) { + result = "add"; + } else if (this->numa_placement == MAP) { + result = "map"; + } + + return result; } |