source: benchmark/readyQ/yield.cpp @ 8e27ac45

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 8e27ac45 was 04b5cef, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added BIAS option to ready_queue
Added yield test for LibFibre?
Fixed some alignments and minor optimizations

  • Property mode set to 100644
File size: 4.3 KB
Line 
1#include <cassert>
2#include <cstdlib>
3#include <cstdio>
4#include <cstring>
5#include <climits>
6
7extern "C" {
8        #include <locale.h>
9        #include <getopt.h>
10}
11
12#include <unistd.h>
13
14#include <chrono>
15
16using Clock = std::chrono::high_resolution_clock;
17using duration_t = std::chrono::duration<double>;
18using std::chrono::nanoseconds;
19
20
21template<typename Ratio, typename T>
22T duration_cast(T seconds) {
23        return std::chrono::duration_cast<std::chrono::duration<T, Ratio>>(std::chrono::duration<T>(seconds)).count();
24}
25
26volatile bool run = false;
27volatile unsigned long long global_counter;
28
29#include "libfibre/fibre.h"
30
31FibreBarrier * barrier;
32struct __attribute__((aligned(128))) counter_t {
33        int value = 0;
34};
35
36void fibre_main( counter_t * counter ) {
37        barrier->wait();
38        // /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
39
40        while(__atomic_load_n(&run, __ATOMIC_RELAXED)) {
41                Fibre::forceYield();
42                // fibre_yield();
43                counter->value++;
44        }
45        __atomic_fetch_add(&global_counter, counter->value, __ATOMIC_SEQ_CST);
46}
47
48int main(int argc, char * argv[]) {
49        double duration = 5;
50        int nprocs = 1;
51        int nthreads = 1;
52
53        std::cout.imbue(std::locale(""));
54        setlocale(LC_ALL, "");
55
56        for(;;) {
57                static struct option options[] = {
58                        {"duration",  required_argument, 0, 'd'},
59                        {"nprocs",    required_argument, 0, 'p'},
60                        {"nthreads",  required_argument, 0, 't'},
61                        {0, 0, 0, 0}
62                };
63
64                int idx = 0;
65                int opt = getopt_long(argc, argv, "d:p:t:", options, &idx);
66
67                const char * arg = optarg ? optarg : "";
68                size_t len = 0;
69                char * end;
70                switch(opt) {
71                        case -1:
72                                goto run;
73                        // Numeric Arguments
74                        case 'd':
75                                duration = strtod(arg, &end);
76                                if(*end != '\0') {
77                                        fprintf(stderr, "Duration must be a valid double, was %s\n", arg);
78                                        goto usage;
79                                }
80                                break;
81                        case 't':
82                                nthreads = strtoul(arg, &end, 10);
83                                if(*end != '\0' || nthreads < 1) {
84                                        fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg);
85                                        goto usage;
86                                }
87                                break;
88                        case 'p':
89                                nprocs = strtoul(arg, &end, 10);
90                                if(*end != '\0' || nprocs < 1) {
91                                        fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg);
92                                        goto usage;
93                                }
94                                break;
95                        // Other cases
96                        default: /* ? */
97                                fprintf( stderr, "Unkown option '%c'\n", opt);
98                        usage:
99                                fprintf( stderr, "Usage: %s [options]\n", argv[0]);
100                                fprintf( stderr, "\n" );
101                                fprintf( stderr, "  -d, --duration=DURATION  Duration of the experiment, in seconds\n" );
102                                fprintf( stderr, "  -t, --nthreads=NTHREADS  Number of kernel threads\n" );
103                                fprintf( stderr, "  -q, --nqueues=NQUEUES    Number of queues per threads\n" );
104                                exit(1);
105                }
106        }
107        run:
108
109        {
110                printf("Running %d threads on %d processors for %lf seconds\n", nthreads, nprocs, duration);
111
112                FibreInit();
113                barrier = new FibreBarrier(nthreads + 1);
114                {
115                        Context::CurrCluster().addWorkers(nprocs);
116                        {
117                                counter_t counters[nthreads];
118                                Fibre threads[nthreads];
119                                for(int i = 0; i < nthreads; i++) {
120                                        threads[i].run(fibre_main, &counters[i]);
121                                }
122                                printf("Starting\n");
123                                bool is_tty = isatty(STDOUT_FILENO);
124                                auto before = Clock::now();
125                                run = true;
126
127                                barrier->wait();
128                                for(;;) {
129                                        usleep(500'000);
130                                        auto now = Clock::now();
131                                        duration_t durr = now - before;
132                                        if( durr.count() > duration ) {
133                                                break;
134                                        }
135                                        if(is_tty) {
136                                                std::cout << "\r" << std::setprecision(4) << durr.count();
137                                                std::cout.flush();
138                                        }
139                                }
140
141                                auto after = Clock::now();
142                                duration_t durr = after - before;
143                                duration = durr.count();
144                                run = false;
145                                printf("\nDone\n");
146                                for(auto & thread : threads) {
147                                        thread.join();
148                                }
149
150                                // for(const auto & counter : counters) {
151                                //      std::cout << counter.value << std::endl;
152                                // }
153                        }
154                }
155
156                auto dur_nano = duration_cast<std::nano>(duration);
157
158                std::cout << "Took " << duration << " s\n";
159                printf("Total yields        : %'15llu\n", global_counter );
160                printf("Yields per procs    : %'15llu\n", global_counter / nprocs );
161                printf("Yields per second   : %'18.2lf\n", ((double)global_counter) / duration );
162                printf("Yields/sec/procs    : %'18.2lf\n", (((double)global_counter) / nprocs) / duration );
163                printf("ns per yields       : %'18.2lf\n", dur_nano / global_counter );
164                printf("ns per yields/procs : %'18.2lf\n", dur_nano / (global_counter / nprocs) );
165
166        }
167}
Note: See TracBrowser for help on using the repository browser.