Advertisement
sci4me

AllTheGollatzV2

Sep 25th, 2018
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 2.81 KB | None | 0 0
  1.  package main
  2.  
  3. import (
  4.     "strconv"
  5.     "strings"
  6.     "fmt"
  7.     "os"
  8.     "os/signal"
  9.     "syscall"
  10.     "runtime"
  11.     "time"
  12.     "flag"
  13. )
  14.  
  15. func comma(v uint64) string {
  16.     sign := ""
  17.     if v < 0 {
  18.         sign = "-"
  19.         v = 0 - v
  20.     }
  21.  
  22.     parts := []string{"", "", "", "", "", "", ""}
  23.     j := len(parts) - 1
  24.  
  25.     for v > 999 {
  26.         parts[j] = strconv.FormatUint(v%1000, 10)
  27.         switch len(parts[j]) {
  28.         case 2:
  29.             parts[j] = "0" + parts[j]
  30.         case 1:
  31.             parts[j] = "00" + parts[j]
  32.         }
  33.         v = v / 1000
  34.         j--
  35.     }
  36.     parts[j] = strconv.Itoa(int(v))
  37.     return sign + strings.Join(parts[j:len(parts)], ",")
  38. }
  39.  
  40. func formatRate(rate float64) string {
  41.     if(rate >= 1000000000) {
  42.         return fmt.Sprintf("%.2f gC/s", rate / 1000000000)
  43.     } else if(rate >= 1000000) {
  44.         return fmt.Sprintf("%.2f mC/s", rate / 1000000)
  45.     } else if(rate >= 1000) {
  46.         return fmt.Sprintf("%.2f kC/s", rate / 1000)
  47.     } else {
  48.         return fmt.Sprintf("%.2f C/s", rate)
  49.     }
  50. }
  51.  
  52. func steps(n uint64) uint64 {
  53.     if n <= 0 { return 0; }
  54.     if n == 1 { return 0; }
  55.  
  56.     var steps uint64
  57.  
  58.     i := n
  59.     for i != 1 {
  60.         for (i & 1) == 1 {
  61.             i = ((3 * i) + 1) / 2
  62.             steps += 2
  63.         }
  64.  
  65.         for (i & 1) == 0 {
  66.             i /= 2
  67.             steps++
  68.         }
  69.     }
  70.  
  71.     return steps
  72. }
  73.  
  74. type work struct {
  75.     start uint64
  76.     end uint64
  77. }
  78.  
  79. type response struct {
  80.     id int
  81.     result uint64
  82. }
  83.  
  84. func worker(id int, req chan work, resp chan response) {
  85.     for {
  86.         w := <- req
  87.  
  88.         var total uint64
  89.         for i := w.start; i < w.end; i++ {
  90.             total += steps(i)
  91.         }
  92.         resp <- response{ id, total }
  93.     }
  94. }
  95.  
  96. func main() {
  97.     var nthreads int
  98.     var blockSize uint64
  99.  
  100.     flag.IntVar(&nthreads, "threads", runtime.NumCPU(), "number of worker threads")
  101.     flag.Uint64Var(&blockSize, "work", 10000000, "work unit size")
  102.     flag.Parse()
  103.  
  104.     if(nthreads <= 0) {
  105.         fmt.Printf("Must have > 0 threads")
  106.         return
  107.     }
  108.  
  109.     fmt.Printf("Running with %d threads, work size %s\n", nthreads, comma(blockSize))
  110.  
  111.     reqs  := make([]chan work, nthreads)
  112.     resps := make(chan response, nthreads)
  113.  
  114.     for i := 0; i < nthreads; i++ {
  115.         reqs[i] = make(chan work)
  116.         go worker(i, reqs[i], resps)
  117.     }
  118.  
  119.     stop := make(chan os.Signal, 2)
  120.     signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
  121.     go func() {
  122.         <-stop
  123.         os.Exit(0)
  124.     }()
  125.  
  126.     startTime := time.Now()
  127.  
  128.     var current uint64
  129.    
  130.     var inFlight = make([]bool, nthreads)
  131.     for i := 0; i < nthreads; i++ {
  132.         inFlight[i] = false
  133.     }
  134.  
  135.     for {  
  136.         for i := 0; i < nthreads; i++ {
  137.             if !inFlight[i] {
  138.                 var w work
  139.                 w.start = current
  140.                 w.end = current + blockSize
  141.                 reqs[i] <- w
  142.                 current += blockSize
  143.                 inFlight[i] = true
  144.             }
  145.         }
  146.  
  147.         loop:
  148.         select {
  149.         case r := <-resps:
  150.             inFlight[r.id] = false
  151.    
  152.             elapsed := time.Since(startTime)
  153.             fmt.Printf("%s | %s | %s\n", elapsed, comma(current), formatRate(float64(current) / float64(elapsed) * float64(time.Second)))
  154.             goto loop
  155.         default:
  156.         }
  157.     }
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement