source: doc/theses/thierry_delisle_PhD/code/processor_list_fast.cpp @ 1e24d13

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

Small tweaks to the memory layout

  • Property mode set to 100644
File size: 3.9 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, unsigned epochs) {
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        struct {
33                std::atomic_size_t write = { 0ul };
34                std::atomic_size_t read  = { 0ul };
35                std::atomic_size_t epoch = { 0ul };
36        } lock_cnt;
37
38        // Flag to signal termination
39        std::atomic_bool done = { false };
40
41        std::thread * threads[nthread];
42        unsigned i = 1;
43        for(auto & t : threads) {
44                t = new std::thread([&done, &list, &barrier, &write_committed, &lock_cnt, writes, epochs](unsigned tid) {
45                        Random rand(tid + rdtscl());
46                        processor proc;
47                        proc.id = list.doregister(&proc);
48                        size_t writes_cnt = 0;
49                        size_t reads_cnt = 0;
50                        size_t epoch_cnt = 0;
51
52                        affinity(tid);
53
54                        barrier.wait(tid);
55
56                        while(__builtin_expect(!done, true)) {
57                                auto r = rand.next() % 100;
58                                if (r < writes) {
59                                        auto n = list.write_lock();
60                                        write_committed++;
61                                        writes_cnt++;
62                                        assert(writes_cnt < -2ul);
63                                        list.write_unlock(n);
64                                }
65                                else if(r < epochs) {
66                                        list.epoch_check();
67                                        epoch_cnt++;
68                                }
69                                else {
70                                        list.read_lock(proc.id);
71                                        reads_cnt++;
72                                        assert(reads_cnt < -2ul);
73                                        list.read_unlock(proc.id);
74                                }
75                        }
76
77                        barrier.wait(tid);
78
79                        auto p = list.unregister(proc.id);
80                        assert(&proc == p);
81                        lock_cnt.write += writes_cnt;
82                        lock_cnt.read  += reads_cnt;
83                        lock_cnt.epoch += epoch_cnt;
84                }, i++);
85        }
86
87        auto before = Clock::now();
88        barrier.wait(0);
89
90        while(true) {
91                usleep(1000);
92                auto now = Clock::now();
93                duration_t durr = now - before;
94                if( durr.count() > duration ) {
95                        done = true;
96                        break;
97                }
98        }
99
100        barrier.wait(0);
101        auto after = Clock::now();
102        duration_t durr = after - before;
103        duration = durr.count();
104
105        for(auto t : threads) {
106                t->join();
107                delete t;
108        }
109
110        assert(write_committed == lock_cnt.write);
111
112        size_t totalop = lock_cnt.read + lock_cnt.write + lock_cnt.epoch;
113        size_t ops_sec = size_t(double(totalop) / duration);
114        size_t ops_thread = ops_sec / nthread;
115        double dur_nano = duration_cast<std::nano>(1.0);
116
117        std::cout << "Duration      : " << duration << "s\n";
118        std::cout << "Total ops     : " << totalop << "(" << lock_cnt.read << "r, " << lock_cnt.write << "w, " << lock_cnt.epoch << "e)\n";
119        std::cout << "Ops/sec       : " << ops_sec << "\n";
120        std::cout << "Ops/sec/thread: " << ops_thread << "\n";
121        std::cout << "ns/Op         : " << ( dur_nano / ops_thread )<< "\n";
122}
123
124void usage(char * argv[]) {
125        std::cerr << argv[0] << ": [DURATION (FLOAT:SEC)] [NTHREADS] [%WRITES]" << std::endl;;
126        std::exit(1);
127}
128
129int main(int argc, char * argv[]) {
130
131        double duration   = 5.0;
132        unsigned nthreads = 2;
133        unsigned writes   = 0;
134        unsigned epochs   = 0;
135
136        std::cout.imbue(std::locale(""));
137
138        switch (argc)
139        {
140        case 5:
141                epochs = std::stoul(argv[4]);
142                [[fallthrough]];
143        case 4:
144                writes = std::stoul(argv[3]);
145                if( (writes + epochs) > 100 ) {
146                        std::cerr << "Writes + Epochs must be valid percentage, was " << argv[3] << " + " << argv[4] << "(" << writes << " + " << epochs << ")" << std::endl;
147                        usage(argv);
148                }
149                [[fallthrough]];
150        case 3:
151                nthreads = std::stoul(argv[2]);
152                [[fallthrough]];
153        case 2:
154                duration = std::stod(argv[1]);
155                if( duration <= 0.0 ) {
156                        std::cerr << "Duration must be positive, was " << argv[1] << "(" << duration << ")" << std::endl;
157                        usage(argv);
158                }
159                [[fallthrough]];
160        case 1:
161                break;
162        default:
163                usage(argv);
164                break;
165        }
166
167        check_cache_line_size();
168
169        std::cout << "Running " << nthreads << " threads for " << duration << " seconds with " << writes << "% writes and " << epochs << "% epochs" << std::endl;
170        run(nthreads, duration, writes, epochs + writes);
171
172        return 0;
173}
Note: See TracBrowser for help on using the repository browser.