#include #include #include #include extern "C" { #include #include } #include #include #include #include "../benchcltr.hfa" extern bool traceHeapOn(); volatile bool run = false; volatile unsigned long long global_counter; thread __attribute__((aligned(128))) Yielder { unsigned long long counter; }; void ?{}( Yielder & this ) { this.counter = 0; ((thread&)this){ "Yielder Thread", *the_benchmark_cluster }; } void main( Yielder & this ) { park( __cfaabi_dbg_ctx ); /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { yield(); this.counter++; } __atomic_fetch_add(&global_counter, this.counter, __ATOMIC_SEQ_CST); } int main(int argc, char * argv[]) { double duration = 5; int nprocs = 1; int nthreads = 1; for(;;) { static struct option options[] = { {"duration", required_argument, 0, 'd'}, {"nprocs", required_argument, 0, 'p'}, {"nthreads", required_argument, 0, 't'}, {0, 0, 0, 0} }; int idx = 0; int opt = getopt_long(argc, argv, "d:p:t:", options, &idx); char * arg = optarg ? optarg : ""; size_t len = 0; char * end; switch(opt) { case -1: goto run; // Numeric Arguments case 'd': duration = strtod(arg, &end); if(*end != '\0') { fprintf(stderr, "Duration must be a valid double, was %s\n", arg); goto usage; } break; case 't': nthreads = strtoul(arg, &end, 10); if(*end != '\0' || nthreads < 1) { fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg); goto usage; } break; case 'p': nprocs = strtoul(arg, &end, 10); if(*end != '\0' || nprocs < 1) { fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg); goto usage; } break; // Other cases default: /* ? */ fprintf( stderr, "Unkown option '%c'\n", opt); usage: fprintf( stderr, "Usage: %s [options]\n", argv[0]); fprintf( stderr, "\n" ); fprintf( stderr, " -d, --duration=DURATION Duration of the experiment, in seconds\n" ); fprintf( stderr, " -t, --nthreads=NTHREADS Number of kernel threads\n" ); fprintf( stderr, " -q, --nqueues=NQUEUES Number of queues per threads\n" ); exit(1); } } run: { printf("Running %d threads on %d processors for %lf seconds\n", nthreads, nprocs, duration); Time start, end; BenchCluster cl; #if !defined(__CFA_NO_STATISTICS__) print_stats_at_exit( cl.self ); #endif { BenchProc procs[nprocs]; { Yielder threads[nthreads]; bool is_tty = isatty(STDOUT_FILENO); printf("Starting\n"); start = getTime(); run = true; for(i; nthreads) { unpark( threads[i] __cfaabi_dbg_ctx2 ); } for() { sleep(500`ms); end = getTime(); if( (end - start) >= duration`s ) { break; } if(is_tty) { printf("\r%.4lf", (double)(end - start)`s); fflush(stdout); } } run = false; end = getTime(); printf("Done\n"); } } printf("Took %'ld ms\n", (end - start)`ms); printf("Total yields : %'15llu\n", global_counter); printf("Yields per procs : %'15llu\n", global_counter / nprocs); printf("Yields per second : %'18.2lf\n", ((double)global_counter) / (end - start)`s); printf("Yields/sec/procs : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s); printf("ns per yields : %'18.2lf\n", ((double)(end - start)`ns) / global_counter); printf("ns per yields/procs : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs)); } }