]> Cypherpunks repositories - gostls13.git/commitdiff
Added fannkuch-parallel.go
authorKyle Consalus <consalus@gmail.com>
Tue, 27 Apr 2010 05:44:44 +0000 (22:44 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 27 Apr 2010 05:44:44 +0000 (22:44 -0700)
R=r, rsc
CC=golang-dev
https://golang.org/cl/978042

test/bench/fannkuch-parallel.go [new file with mode: 0644]
test/bench/fannkuch-parallel.txt [new file with mode: 0644]
test/bench/timing.sh

diff --git a/test/bench/fannkuch-parallel.go b/test/bench/fannkuch-parallel.go
new file mode 100644 (file)
index 0000000..7897eac
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+    * Neither the name of "The Computer Language Benchmarks Game" nor the
+    name of "The Computer Language Shootout Benchmarks" nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * The Computer Language Benchmarks Game
+ * http://shootout.alioth.debian.org/
+ *
+ * contributed by The Go Authors.
+ * Based on fannkuch.scala by Rex Kerr
+ */
+
+package main
+
+import (
+       "flag"
+       "fmt"
+       "runtime"
+)
+
+var n = flag.Int("n", 7, "count")
+var nCPU = flag.Int("ncpu", 2, "number of cpus")
+
+type Job struct {
+       start []int
+       n     int
+}
+
+type Found struct {
+       who *Kucher
+       k   int
+}
+
+type Kucher struct {
+       perm []int
+       temp []int
+       flip []int
+       in   chan Job
+}
+
+func NewKucher(length int) *Kucher {
+       return &Kucher{
+               perm: make([]int, length),
+               temp: make([]int, length),
+               flip: make([]int, length),
+               in:   make(chan Job),
+       }
+}
+
+func (k *Kucher) permute(n int) bool {
+       i := 0
+       for ; i < n-1 && k.flip[i] == 0; i++ {
+               t := k.perm[0]
+               j := 0
+               for ; j <= i; j++ {
+                       k.perm[j] = k.perm[j+1]
+               }
+               k.perm[j] = t
+       }
+       k.flip[i]--
+       for i > 0 {
+               i--
+               k.flip[i] = i
+       }
+       return k.flip[n-1] >= 0
+}
+
+func (k *Kucher) count() int {
+       K := 0
+       copy(k.temp, k.perm)
+       for k.temp[0] != 0 {
+               m := k.temp[0]
+               for i := 0; i < m; i++ {
+                       k.temp[i], k.temp[m] = k.temp[m], k.temp[i]
+                       m--
+               }
+               K++
+       }
+       return K
+}
+
+func (k *Kucher) Run(foreman chan<- Found) {
+       for job := range k.in {
+               verbose := 30
+               copy(k.perm, job.start)
+               for i, v := range k.perm {
+                       if v != i {
+                               verbose = 0
+                       }
+                       k.flip[i] = i
+               }
+               K := 0
+               for {
+                       if verbose > 0 {
+                               for _, p := range k.perm {
+                                       fmt.Print(p + 1)
+                               }
+                               fmt.Println()
+                               verbose--
+                       }
+                       count := k.count()
+                       if count > K {
+                               K = count
+                       }
+                       if !k.permute(job.n) {
+                               break
+                       }
+               }
+               foreman <- Found{k, K}
+       }
+}
+
+type Fanner struct {
+       jobind   int
+       jobsdone int
+       k        int
+       jobs     []Job
+       workers  []*Kucher
+       in       chan Found
+       result   chan int
+}
+
+func NewFanner(jobs []Job, workers []*Kucher) *Fanner {
+       return &Fanner{
+               jobs: jobs, workers: workers,
+               in:     make(chan Found),
+               result: make(chan int),
+       }
+}
+
+func (f *Fanner) Run(N int) {
+       for msg := range f.in {
+               if msg.k > f.k {
+                       f.k = msg.k
+               }
+               if msg.k >= 0 {
+                       f.jobsdone++
+               }
+               if f.jobind < len(f.jobs) {
+                       msg.who.in <- f.jobs[f.jobind]
+                       f.jobind++
+               } else if f.jobsdone == len(f.jobs) {
+                       f.result <- f.k
+                       return
+               }
+       }
+}
+
+func swapped(a []int, i, j int) []int {
+       b := make([]int, len(a))
+       copy(b, a)
+       b[i], b[j] = a[j], a[i]
+       return b
+}
+
+func main() {
+       flag.Parse()
+       runtime.GOMAXPROCS(*nCPU)
+       N := *n
+       base := make([]int, N)
+       for i := range base {
+               base[i] = i
+       }
+
+       njobs := 1
+       if N > 8 {
+               njobs += (N*(N-1))/2 - 28 // njobs = 1 + sum(8..N-1) = 1 + sum(1..N-1) - sum(1..7)
+       }
+       jobs := make([]Job, njobs)
+       jobsind := 0
+
+       firstN := N
+       if firstN > 8 {
+               firstN = 8
+       }
+       jobs[jobsind] = Job{base, firstN}
+       jobsind++
+       for i := N - 1; i >= 8; i-- {
+               for j := 0; j < i; j++ {
+                       jobs[jobsind] = Job{swapped(base, i, j), i}
+                       jobsind++
+               }
+       }
+
+       nworkers := *nCPU
+       if njobs < nworkers {
+               nworkers = njobs
+       }
+       workers := make([]*Kucher, nworkers)
+       foreman := NewFanner(jobs, workers)
+       go foreman.Run(N)
+       for i := range workers {
+               k := NewKucher(N)
+               workers[i] = k
+               go k.Run(foreman.in)
+               foreman.in <- Found{k, -1}
+       }
+       fmt.Printf("Pfannkuchen(%d) = %d\n", N, <-foreman.result)
+}
diff --git a/test/bench/fannkuch-parallel.txt b/test/bench/fannkuch-parallel.txt
new file mode 100644 (file)
index 0000000..e66f779
--- /dev/null
@@ -0,0 +1,31 @@
+1234567
+2134567
+2314567
+3214567
+3124567
+1324567
+2341567
+3241567
+3421567
+4321567
+4231567
+2431567
+3412567
+4312567
+4132567
+1432567
+1342567
+3142567
+4123567
+1423567
+1243567
+2143567
+2413567
+4213567
+2345167
+3245167
+3425167
+4325167
+4235167
+2435167
+Pfannkuchen(7) = 16
index 7543834fbdf78aa7e831152cd261c6240c8bd50f..83ffd2494c8157b6db06d7044479b4693d3d0589 100755 (executable)
@@ -106,7 +106,9 @@ fannkuch() {
        runonly echo 'fannkuch 12'
        run 'gcc -O2 fannkuch.c' a.out 12
        run 'gccgo -O2 fannkuch.go' a.out -n 12
+       run 'gccgo -O2 fannkuch-parallel.go' a.out -n 12
        run 'gc fannkuch' $O.out -n 12
+       run 'gc fannkuch-parallel' $O.out -n 12
        run 'gc_B fannkuch' $O.out -n 12
 }