goroutine を使ってみた

Go 翻訳プロジェクトが立ち上がったようですね。チュートリアルのかなりの部分がもう訳されてます。
http://go.shibu.jp/

遊んでるうちに、将来は C に取って代わりそうだなという気がしてきました。

昨日のコードの goroutine 版が動きました。まだ goroutine がどういうものかさっぱりわからないので、使い方が間違ってる可能性大ですが。
ちょっと新人いじめがすぎました。遅いです。いや、使い方が間違ってるほうが大きいかもしれないけど。

(追記) うわさの runtime.GOMAXPROCS つけたらものすごく速くなった!使えるかもと思った。コードは差し替えておきます。
4CPU割り当ててやってみたらむしろ遅くなったw みんな並列じゃ苦労してるんだねw

以下、コード

package main

import (
	"math";
	"fmt";
	"os";
	"runtime";
	"container/vector";
)

const (
	K	= 4;
	N	= 2;
)

const channelBufferNum = 2048

type DeBruijnSeq struct {
	k, n, max	int;
	out		chan *vector.IntVector;	// for output
	count		chan int;
}

type DeBruijnSeqResult struct {
	ch	chan *vector.IntVector;
	result	chan *vector.Vector;
}

func Init(k, n int) (d *DeBruijnSeq, result *DeBruijnSeqResult, ok bool) {
	if k < 2 || 10 < k {
		return nil, nil, false
	}
	if n < 1 {
		return nil, nil, false
	}

	max := math.Pow(float64(k), float64(n));
	if float64(0x7FFFFFFF) < max {
		return nil, nil, false
	}

	out, result := startOutputServer();
	count := make(chan int, channelBufferNum);
	return &DeBruijnSeq{k, n, int(max), out, count}, result, true;
}

func (d *DeBruijnSeq) Search() {
	a := vector.NewIntVector(d.n);
	for i := 0; i < d.n; i++ {
		a.Set(i, 0)
	}
	go d.searchCore(a);
}

func (d *DeBruijnSeq) searchCore(a *vector.IntVector) {
	// 重複判定
	if !d.isUnique(a) {
		d.count <- -1;
		return;
	}

	// 完成判定
	if d.isComplete(a) {
		//fmt.Println( " comp! " );
		d.out <- a;
		d.count <- -1;
		return;
	}

	// 次の反復へ
	for i := 0; i < d.k; i++ {
		d.count <- 1;
		b := vector.NewIntVector(0);
		b.AppendVector(a);	// copy
		b.Push(i);
		go d.searchCore(b);
	}
	d.count <- -1;
}

func (d *DeBruijnSeq) isUnique(a *vector.IntVector) bool {
	if a.Vector.Len() <= d.n {
		return true
	}

	pos := a.Vector.Len() - d.n;

	for i := 0; i < pos; i++ {
		if sequenceEqual(a, i, pos, d.n) {
			return false
		}
	}
	return true;
}

func sequenceEqual(v *vector.IntVector, a, b, len int) bool {
	for i := 0; i < len; i++ {
		if v.At(a) != v.At(b) {
			return false
		}
		a++;
		b++;
	}
	return true;
}

func (d *DeBruijnSeq) isComplete(a *vector.IntVector) bool {
	if a.Vector.Len() != d.max {
		return false
	}

	b := vector.NewIntVector(0);
	b.AppendVector(a);	// copy

	for i := 0; i < d.n-1; i++ {
		b.Push(b.At(i));
		if !d.isUnique(b) {
			return false
		}
	}
	return true;
}

func startOutputServer() (chan *vector.IntVector, *DeBruijnSeqResult) {
	out := make(chan *vector.IntVector, channelBufferNum);
	result := make(chan *vector.Vector, 2);
	go output(out, result);
	return out, &DeBruijnSeqResult{out, result};
}

func output(in chan *vector.IntVector, out chan *vector.Vector) {
	v := vector.New(0);
	for !closed(in) {
		if data := <- in; data != nil {
			//fmt.Println( data );
			v.Push(data);
		}
	}
	out <- v;
}

func main() {
	runtime.GOMAXPROCS(2);

	d, result, ok := Init(K, N);
	if !ok {
		os.Exit(1)
	}

	d.Search();
	for numOfGor := 1; numOfGor != 0; {
		numOfGor += <-d.count
	}
	close(result.ch);
	n := <-result.result;

	fmt.Println(n.Len());
}