source: doc/theses/thierry_delisle_PhD/code/processor_list_fast.cpp @ b2a37b0

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since b2a37b0 was b2a37b0, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Initial drafts in C++ of the CFA scheduler

  • Property mode set to 100644
File size: 3.5 KB
Line 
1#include "processor_list.hpp"
2
3#include <array>
4#include <iomanip>
5#include <iostream>
6#include <locale>
7#include <string>
8#include <thread>
9
10#include "utils.hpp"
11
12unsigned num() {
13        return 0x1000000;
14}
15
16//-------------------
17
18struct processor {
19        unsigned id;
20};
21void run(unsigned nthread, double duration, unsigned writes) {
22        assert(writes < 100);
23
24        // List being tested
25        processor_list list = {};
26
27        // Barrier for synchronization
28        barrier_t barrier(nthread + 1);
29
30        // Data to check everything is OK
31        size_t write_committed = 0ul;
32        std::atomic_size_t lock_cnt_write = { 0ul };
33        std::atomic_size_t lock_cnt_read  = { 0ul };
34
35        // Flag to signal termination
36        std::atomic_bool done = { false };
37
38        std::thread * threads[nthread];
39        unsigned i = 1;
40        for(auto & t : threads) {
41                t = new std::thread([&done, &list, &barrier, &write_committed, &lock_cnt_write, &lock_cnt_read, writes](unsigned tid) {
42                        Random rand(tid + rdtscl());
43                        processor proc;
44                        proc.id = list.doregister(&proc);
45                        size_t writes_cnt = 0;
46                        size_t reads_cnt = 0;
47
48                        affinity(tid);
49
50                        barrier.wait(tid);
51
52                        while(__builtin_expect(!done, true)) {
53                                if ((rand.next() % 100) < writes) {
54                                        auto n = list.write_lock();
55                                        write_committed++;
56                                        writes_cnt++;
57                                        assert(writes_cnt < -2ul);
58                                        list.write_unlock(n);
59                                }
60                                else {
61                                        list.read_lock(proc.id);
62                                        reads_cnt++;
63                                        assert(reads_cnt < -2ul);
64                                        list.read_unlock(proc.id);
65                                }
66                        }
67
68                        barrier.wait(tid);
69
70                        auto p = list.unregister(proc.id);
71                        assert(&proc == p);
72                        lock_cnt_write += writes_cnt;
73                        lock_cnt_read  += reads_cnt;
74                }, i++);
75        }
76
77        auto before = Clock::now();
78        barrier.wait(0);
79
80        while(true) {
81                usleep(1000);
82                auto now = Clock::now();
83                duration_t durr = now - before;
84                if( durr.count() > duration ) {
85                        done = true;
86                        break;
87                }
88        }
89
90        barrier.wait(0);
91        auto after = Clock::now();
92        duration_t durr = after - before;
93        duration = durr.count();
94
95        for(auto t : threads) {
96                t->join();
97                delete t;
98        }
99
100        assert(write_committed == lock_cnt_write);
101
102        size_t ops_sec = size_t(double(lock_cnt_read + lock_cnt_write) / duration);
103        size_t ops_thread = ops_sec / nthread;
104        double dur_nano = duration_cast<std::nano>(1.0);
105
106        std::cout << "Duration      : " << duration << "s\n";
107        std::cout << "Total ops     : " << (lock_cnt_read + lock_cnt_write) << "(" << lock_cnt_read << "r, " << lock_cnt_write << "w)\n";
108        std::cout << "Ops/sec       : " << ops_sec << "\n";
109        std::cout << "Ops/sec/thread: " << ops_thread << "\n";
110        std::cout << "ns/Op         : " << ( dur_nano / ops_thread )<< "\n";
111}
112
113void usage(char * argv[]) {
114        std::cerr << argv[0] << ": [DURATION (FLOAT:SEC)] [NTHREADS] [%WRITES]" << std::endl;;
115        std::exit(1);
116}
117
118int main(int argc, char * argv[]) {
119
120        double duration   = 5.0;
121        unsigned nthreads = 2;
122        unsigned writes   = 0;
123
124        std::cout.imbue(std::locale(""));
125
126        switch (argc)
127        {
128        case 4:
129                writes = std::stoul(argv[3]);
130                if( writes >= 100 ) {
131                        std::cerr << "Writes must be valid percentage, was " << argv[3] << "(" << writes << ")" << std::endl;
132                        usage(argv);
133                }
134                [[fallthrough]];
135        case 3:
136                nthreads = std::stoul(argv[2]);
137                [[fallthrough]];
138        case 2:
139                duration = std::stod(argv[1]);
140                if( duration <= 0.0 ) {
141                        std::cerr << "Duration must be positive, was " << argv[1] << "(" << duration << ")" << std::endl;
142                        usage(argv);
143                }
144                [[fallthrough]];
145        case 1:
146                break;
147        default:
148                usage(argv);
149                break;
150        }
151
152        check_cache_line_size();
153
154        std::cout << "Running " << nthreads << " threads for " << duration << " seconds with " << writes << "% writes" << std::endl;
155        run(nthreads, duration, writes);
156
157        return 0;
158}
Note: See TracBrowser for help on using the repository browser.