Changeset 2c7eee0


Ignore:
Timestamp:
Nov 3, 2020, 1:21:36 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
dbb1073
Parents:
58688bf
Message:

Fixed cycle benchmark to avoid extra unmatched unpark.
Added libfibre implementation.
Split out go common code into bench.go

Location:
benchmark/readyQ
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • benchmark/readyQ/cycle.cfa

    r58688bf r2c7eee0  
    11#include "rq_bench.hfa"
    22
    3 thread Partner {
    4         Partner * partner;
     3struct Partner {
    54        unsigned long long count;
     5        unsigned long long blocks;
     6        bench_sem self;
     7        bench_sem * next;
    68};
    79
    810void ?{}( Partner & this ) {
    9         ((thread&)this){ bench_cluster };
     11        this.count = this.blocks = 0;
    1012}
    1113
    12 void main( Partner & this ) {
    13         this.count = 0;
     14thread BThrd {
     15        Partner & partner;
     16};
     17
     18void ?{}( BThrd & this, Partner * partner ) {
     19        ((thread&)this){ bench_cluster };
     20        &this.partner = partner;
     21}
     22
     23void ^?{}( BThrd & mutex this ) {}
     24
     25void main( BThrd & thrd ) with(thrd.partner) {
     26        count = 0;
    1427        for() {
    15                 park();
    16                 unpark( *this.partner );
    17                 this.count ++;
     28                blocks += wait( self );
     29                post( *next );
     30                count ++;
    1831                if( clock_mode && stop) break;
    19                 if(!clock_mode && this.count >= stop_count) break;
     32                if(!clock_mode && count >= stop_count) break;
    2033        }
    2134
     
    3346        {
    3447                unsigned long long global_counter = 0;
     48                unsigned long long global_blocks  = 0;
    3549                unsigned tthreads = nthreads * ring_size;
    3650                Time start, end;
     
    3852                {
    3953                        threads_left = tthreads;
    40                         Partner threads[tthreads];
     54                        BThrd * threads[tthreads];
     55                        Partner thddata[tthreads];
    4156                        for(i; tthreads) {
    4257                                unsigned pi = (i + nthreads) % tthreads;
    43                                 threads[i].partner = &threads[pi];
     58                                thddata[i].next = &thddata[pi].self;
     59                        }
     60                        for(int i = 0; i < tthreads; i++) {
     61                                threads[i] = malloc();
     62                                (*threads[i]){ &thddata[i] };
    4463                        }
    4564                        printf("Starting\n");
     
    4968
    5069                        for(i; nthreads) {
    51                                 unpark( threads[i] );
     70                                post( thddata[i].self );
    5271                        }
    5372                        wait(start, is_tty);
     
    5877
    5978                        for(i; tthreads) {
    60                                 global_counter += join( threads[i] ).count;
     79                                Partner & partner = join( *threads[i] ).partner;
     80                                global_counter += partner.count;
     81                                global_blocks  += partner.blocks;
     82                                delete(threads[i]);
    6183                        }
    6284                }
    6385
    64                 printf("Duration (ms)       : %'ld\n", (end - start)`ms);
    65                 printf("Number of processors: %'d\n", nprocs);
    66                 printf("Number of threads   : %'d\n", tthreads);
    67                 printf("Cycle size (# thrds): %'d\n", ring_size);
    68                 printf("Yields per second   : %'18.2lf\n", ((double)global_counter) / (end - start)`s);
    69                 printf("ns per yields       : %'18.2lf\n", ((double)(end - start)`ns) / global_counter);
    70                 printf("Total yields        : %'15llu\n", global_counter);
    71                 printf("Yields per threads  : %'15llu\n", global_counter / tthreads);
    72                 printf("Yields per procs    : %'15llu\n", global_counter / nprocs);
    73                 printf("Yields/sec/procs    : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s);
    74                 printf("ns per yields/procs : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs));
     86                printf("Duration (ms)        : %'ld\n", (end - start)`ms);
     87                printf("Number of processors : %'d\n", nprocs);
     88                printf("Number of threads    : %'d\n", tthreads);
     89                printf("Cycle size (# thrds) : %'d\n", ring_size);
     90                printf("Total Operations(ops): %'15llu\n", global_counter);
     91                printf("Total blocks         : %'15llu\n", global_blocks);
     92                printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / (end - start)`s);
     93                printf("ns per ops           : %'18.2lf\n", ((double)(end - start)`ns) / global_counter);
     94                printf("Ops per threads      : %'15llu\n", global_counter / tthreads);
     95                printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
     96                printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s);
     97                printf("ns per ops/procs     : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs));
    7598                fflush(stdout);
    7699        }
  • benchmark/readyQ/cycle.cpp

    r58688bf r2c7eee0  
     1
     2#include "rq_bench.hpp"
     3
     4struct Partner {
     5        unsigned long long count  = 0;
     6        unsigned long long blocks = 0;
     7        bench_sem self;
     8        bench_sem * next;
     9};
     10
     11void partner_main( Partner * self ) {
     12        self->count = 0;
     13        for(;;) {
     14                self->blocks += self->self.wait();
     15                self->next->post();
     16                self->count ++;
     17                if( clock_mode && stop) break;
     18                if(!clock_mode && self->count >= stop_count) break;
     19        }
     20
     21        __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST);
     22}
     23
     24int main(int argc, char * argv[]) {
     25        unsigned ring_size = 2;
     26        option_t opt[] = {
     27                BENCH_OPT,
     28                { 'r', "ringsize", "Number of threads in a cycle", ring_size }
     29        };
     30        BENCH_OPT_PARSE("cforall cycle benchmark");
     31
     32        {
     33                unsigned long long global_counter = 0;
     34                unsigned long long global_blocks  = 0;
     35                unsigned tthreads = nthreads * ring_size;
     36                uint64_t start, end;
     37                FibreInit(1, nprocs);
     38                {
     39                        threads_left = tthreads;
     40                        Fibre * threads[tthreads];
     41                        Partner thddata[tthreads];
     42                        for(int i = 0; i < tthreads; i++) {
     43                                unsigned pi = (i + nthreads) % tthreads;
     44                                thddata[i].next = &thddata[pi].self;
     45                        }
     46                        for(int i = 0; i < tthreads; i++) {
     47                                threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(partner_main), &thddata[i] );
     48                        }
     49                        printf("Starting\n");
     50
     51                        bool is_tty = isatty(STDOUT_FILENO);
     52                        start = getTimeNsec();
     53
     54                        for(int i = 0; i < nthreads; i++) {
     55                                thddata[i].self.post();
     56                        }
     57                        wait(start, is_tty);
     58
     59                        stop = true;
     60                        end = getTimeNsec();
     61                        printf("\nDone\n");
     62
     63                        for(int i = 0; i < tthreads; i++) {
     64                                fibre_join( threads[i], nullptr );
     65                                global_counter += thddata[i].count;
     66                                global_blocks  += thddata[i].blocks;
     67                        }
     68                }
     69
     70                printf("Duration (ms)        : %'ld\n", to_miliseconds(end - start));
     71                printf("Number of processors : %'d\n", nprocs);
     72                printf("Number of threads    : %'d\n", tthreads);
     73                printf("Cycle size (# thrds) : %'d\n", ring_size);
     74                printf("Total Operations(ops): %'15llu\n", global_counter);
     75                printf("Total blocks         : %'15llu\n", global_blocks);
     76                printf("Ops per second       : %'18.2lf\n", ((double)global_counter) / to_fseconds(end - start));
     77                printf("ns per ops           : %'18.2lf\n", ((double)(end - start)) / global_counter);
     78                printf("Ops per threads      : %'15llu\n", global_counter / tthreads);
     79                printf("Ops per procs        : %'15llu\n", global_counter / nprocs);
     80                printf("Ops/sec/procs        : %'18.2lf\n", (((double)global_counter) / nprocs) / to_fseconds(end - start));
     81                printf("ns per ops/procs     : %'18.2lf\n", ((double)(end - start)) / (global_counter / nprocs));
     82                fflush(stdout);
     83        }
     84
     85        return 0;
     86}
  • benchmark/readyQ/cycle.go

    r58688bf r2c7eee0  
    22
    33import (
    4         "bufio"
    54        "flag"
    65        "fmt"
    7         "os"
    8         "runtime"
    96        "sync/atomic"
    107        "time"
     
    129        "golang.org/x/text/message"
    1310)
    14 
    15 var clock_mode bool
    16 var threads_left int64
    17 var stop int32
    18 var duration float64
    19 var stop_count uint64
    20 
    21 func fflush(f *bufio.Writer) {
    22         defer f.Flush()
    23         f.Write([]byte("\r"))
    24 }
    25 
    26 func wait(start time.Time, is_tty bool) {
    27         f := bufio.NewWriter(os.Stdout)
    28         tdur := time.Duration(duration)
    29         for true {
    30                 time.Sleep(100 * time.Millisecond)
    31                 end := time.Now()
    32                 delta := end.Sub(start)
    33                 if is_tty {
    34                         fmt.Printf(" %.1f",delta.Seconds())
    35                         fflush(f)
    36                 }
    37                 if clock_mode && delta >= (tdur * time.Second) {
    38                         break
    39                 } else if !clock_mode && atomic.LoadInt64(&threads_left) == 0 {
    40                         break
    41                 }
    42         }
    43 }
    4411
    4512func partner(result chan uint64, mine chan int, next chan int) {
     
    5825
    5926func main() {
    60         var nprocs int
    61         var nthreads int
    6227        var ring_size int
    6328
    64         nprocsOpt := flag.Int("p", 1, "The number of processors")
    65         nthreadsOpt := flag.Int("t", 1, "The number of threads")
    6629        ring_sizeOpt := flag.Int("r", 2, "The number of threads per cycles")
    67         durationOpt := flag.Float64("d", 0, "Duration of the experiment in seconds")
    68         stopOpt := flag.Uint64("i", 0, "Duration of the experiment in iterations")
    6930
    70         flag.Parse()
     31        bench_init()
    7132
    72         nprocs = *nprocsOpt
    73         nthreads = *nthreadsOpt
    7433        ring_size = *ring_sizeOpt
    75         duration = *durationOpt
    76         stop_count = *stopOpt
    7734
    78         if duration > 0 && stop_count > 0 {
    79                 panic(fmt.Sprintf("--duration and --iterations cannot be used together\n"))
    80         } else if duration > 0 {
    81                 clock_mode = true
    82                 stop_count = 0xFFFFFFFFFFFFFFFF
    83                 fmt.Printf("Running for %f seconds\n", duration)
    84         } else if stop_count > 0 {
    85                 clock_mode = false
    86                 fmt.Printf("Running for %d iterations\n", stop_count)
    87         } else {
    88                 duration = 5
    89                 clock_mode = true
    90                 fmt.Printf("Running for %f seconds\n", duration)
    91         }
    92 
    93         runtime.GOMAXPROCS(nprocs)
    9435        tthreads := nthreads * ring_size
    9536        threads_left = int64(tthreads)
     
    12667
    12768        p := message.NewPrinter(language.English)
    128         p.Printf("Duration (ms)       : %f\n", delta.Seconds());
    129         p.Printf("Number of processors: %d\n", nprocs);
    130         p.Printf("Number of threads   : %d\n", tthreads);
    131         p.Printf("Cycle size (# thrds): %d\n", ring_size);
    132         p.Printf("Yields per second   : %18.2f\n", float64(global_counter) / delta.Seconds())
    133         p.Printf("ns per yields       : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
    134         p.Printf("Total yields        : %15d\n", global_counter)
    135         p.Printf("Yields per threads  : %15d\n", global_counter / uint64(tthreads))
    136         p.Printf("Yields per procs    : %15d\n", global_counter / uint64(nprocs))
    137         p.Printf("Yields/sec/procs    : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
    138         p.Printf("ns per yields/procs : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
     69        p.Printf("Duration (ms)        : %f\n", delta.Seconds());
     70        p.Printf("Number of processors : %d\n", nprocs);
     71        p.Printf("Number of threads    : %d\n", tthreads);
     72        p.Printf("Cycle size (# thrds) : %d\n", ring_size);
     73        p.Printf("Total Operations(ops): %15d\n", global_counter)
     74        p.Printf("Yields per second    : %18.2f\n", float64(global_counter) / delta.Seconds())
     75        p.Printf("ns per ops           : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
     76        p.Printf("Ops per threads      : %15d\n", global_counter / uint64(tthreads))
     77        p.Printf("Ops per procs        : %15d\n", global_counter / uint64(nprocs))
     78        p.Printf("Ops/sec/procs        : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
     79        p.Printf("ns per ops/procs    : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
    13980
    14081}
  • benchmark/readyQ/rq_bench.hfa

    r58688bf r2c7eee0  
    6666
    6767void ^?{}( BenchCluster & this ) {
    68         adelete( this.nprocs, this.procs );
     68        adelete( this.procs );
    6969        ^(this.cl){};
    7070}
     
    8787        }
    8888}
     89
     90struct bench_sem {
     91        struct $thread * volatile ptr;
     92};
     93
     94static inline {
     95        void  ?{}(bench_sem & this) {
     96                this.ptr = 0p;
     97        }
     98
     99        void ^?{}(bench_sem & this) {}
     100
     101        bool wait(bench_sem & this) {
     102                for() {
     103                        struct $thread * expected = this.ptr;
     104                        if(expected == 1p) {
     105                                if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     106                                        return false;
     107                                }
     108                        }
     109                        else {
     110                                /* paranoid */ verify( expected == 0p );
     111                                if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     112                                        park();
     113                                        return true;
     114                                }
     115                        }
     116
     117                }
     118        }
     119
     120        bool post(bench_sem & this) {
     121                for() {
     122                        struct $thread * expected = this.ptr;
     123                        if(expected == 1p) return false;
     124                        if(expected == 0p) {
     125                                if(__atomic_compare_exchange_n(&this.ptr, &expected, 1p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     126                                        return false;
     127                                }
     128                        }
     129                        else {
     130                                if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
     131                                        unpark( expected );
     132                                        return true;
     133                                }
     134                        }
     135                }
     136        }
     137}
Note: See TracChangeset for help on using the changeset viewer.