mirror of
https://github.com/golang/go
synced 2024-11-21 23:04:39 -07:00
Added fannkuch-parallel.go
R=r, rsc CC=golang-dev https://golang.org/cl/978042
This commit is contained in:
parent
22f84c5b2a
commit
8b9a73f6a1
224
test/bench/fannkuch-parallel.go
Normal file
224
test/bench/fannkuch-parallel.go
Normal file
@ -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)
|
||||
}
|
31
test/bench/fannkuch-parallel.txt
Normal file
31
test/bench/fannkuch-parallel.txt
Normal file
@ -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
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user