source: benchmark/readyQ/locality.go@ 2dd0689

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum stuck-waitfor-destruct
Last change on this file since 2dd0689 was 2dd0689, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Fix implementation of locality to properly use spots.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1package main
2
3import (
4 "context"
5 "flag"
6 "fmt"
7 "math/rand"
8 "os"
9 "sync/atomic"
10 "time"
11 "unsafe"
12 "golang.org/x/sync/semaphore"
13 "golang.org/x/text/language"
14 "golang.org/x/text/message"
15)
16
17type GoCtx struct {
18 s * semaphore.Weighted
19 d * [] uint64
20}
21
22type Spot struct {
23 ptr uintptr
24}
25
26func (this * Spot) put( s * semaphore.Weighted, data [] uint64, share bool) ([] uint64) {
27 ctx := GoCtx{s, &data}
28
29 var raw uintptr
30 for true {
31 raw = this.ptr
32 if raw == uintptr(1) {
33 return nil
34 }
35 if atomic.CompareAndSwapUintptr(&this.ptr, raw, uintptr(unsafe.Pointer(&ctx))) {
36 break
37 }
38 }
39
40 if raw != uintptr(0) {
41 val := (*GoCtx)(unsafe.Pointer(raw))
42 if share {
43 val.d = &data
44 }
45
46 val.s.Release(1)
47 }
48
49 ctx.s.Acquire(context.Background(), 1)
50
51 return *ctx.d
52}
53
54func (this * Spot) release() {
55 val := (*GoCtx)(unsafe.Pointer(atomic.SwapUintptr(&this.ptr, uintptr(1))))
56 if val == nil {
57 return
58 }
59
60 val.s.Release(1)
61}
62
63
64
65func local(result chan uint64, start chan struct{}, size uint64, cnt uint64, channels [] Spot, share bool) {
66 lrand := rand.New(rand.NewSource(rand.Int63()))
67 var data [] uint64
68 data = make([]uint64, size)
69 for i := uint64(0); i < size; i++ {
70 data[i] = 0
71 }
72
73 sem := semaphore.NewWeighted(1)
74 sem.Acquire(context.Background(), 1)
75
76 count := uint64(0)
77 <- start
78 for true {
79 for i := uint64(0); i < cnt; i++ {
80 data[lrand.Uint64() % size] += 1
81 }
82
83 i := lrand.Int() % len(channels)
84 data = channels[i].put(sem, data, share)
85 count += 1
86
87 if clock_mode && atomic.LoadInt32(&stop) == 1 { break }
88 if !clock_mode && count >= stop_count { break }
89 if uint64(len(data)) != size {
90 panic("Data has weird size")
91 }
92 }
93
94 atomic.AddInt64(&threads_left, -1);
95 result <- count
96}
97
98func main() {
99 work_sizeOpt := flag.Uint64("w", 2 , "Number of words (uint64) per threads")
100 countOpt := flag.Uint64("c", 2 , "Number of words (uint64) to touch")
101 shareOpt := flag.Bool ("s", false, "Pass the work data to the next thread when blocking")
102
103 defer bench_init()()
104
105 size := *work_sizeOpt
106 cnt := *countOpt
107 share := *shareOpt
108
109 if ! (nthreads > nprocs) {
110 fmt.Fprintf(os.Stderr, "Must have more threads than procs\n")
111 os.Exit(1)
112 }
113
114 barrierStart := make(chan struct{})
115 threads_left = int64(nthreads)
116 result := make(chan uint64)
117 channels := make([]Spot, nthreads - nprocs)
118 for i := range channels {
119 channels[i] = Spot{uintptr(0)}
120 }
121
122 for i := 0; i < nthreads; i++ {
123 go local(result, barrierStart, size, cnt, channels, share)
124 }
125 fmt.Printf("Starting\n");
126
127 atomic.StoreInt32(&stop, 0)
128 start := time.Now()
129 close(barrierStart)
130
131 wait(start, true);
132
133 atomic.StoreInt32(&stop, 1)
134 end := time.Now()
135 delta := end.Sub(start)
136
137 fmt.Printf("\nDone\n")
138
139 for i := range channels {
140 channels[i].release()
141 }
142
143 global_counter := uint64(0)
144 for i := 0; i < nthreads; i++ {
145 global_counter += <- result
146 }
147
148 p := message.NewPrinter(language.English)
149 p.Printf("Duration (ms) : %f\n", delta.Seconds());
150 p.Printf("Number of processors : %d\n", nprocs);
151 p.Printf("Number of threads : %d\n", nthreads);
152 p.Printf("Work size (64bit words): %d\n", size);
153 p.Printf("Total Operations(ops) : %15d\n", global_counter)
154 p.Printf("Ops per second : %18.2f\n", float64(global_counter) / delta.Seconds())
155 p.Printf("ns per ops : %18.2f\n", float64(delta.Nanoseconds()) / float64(global_counter))
156 p.Printf("Ops per threads : %15d\n", global_counter / uint64(nthreads))
157 p.Printf("Ops per procs : %15d\n", global_counter / uint64(nprocs))
158 p.Printf("Ops/sec/procs : %18.2f\n", (float64(global_counter) / float64(nprocs)) / delta.Seconds())
159 p.Printf("ns per ops/procs : %18.2f\n", float64(delta.Nanoseconds()) / (float64(global_counter) / float64(nprocs)))
160}
Note: See TracBrowser for help on using the repository browser.