From c12ccabb9c85130e7ba779ab0e1e64263332af54 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 7 Aug 2009 15:28:46 -0700 Subject: [PATCH] chameneos R=rsc DELTA=514 (513 added, 0 deleted, 1 changed) OCL=32898 CL=32910 --- test/bench/chameneosredux.c | 330 ++++++++++++++++++++++++++++++++++ test/bench/chameneosredux.go | 202 +++++++++++++++++++++ test/bench/chameneosredux.txt | 28 +++ test/bench/timing.log | 4 + test/bench/timing.sh | 9 +- 5 files changed, 572 insertions(+), 1 deletion(-) create mode 100644 test/bench/chameneosredux.c create mode 100644 test/bench/chameneosredux.go create mode 100644 test/bench/chameneosredux.txt diff --git a/test/bench/chameneosredux.c b/test/bench/chameneosredux.c new file mode 100644 index 00000000000..ed78c31d7ba --- /dev/null +++ b/test/bench/chameneosredux.c @@ -0,0 +1,330 @@ +/* +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 Michael Barker + based on a Java contribution by Luzius Meisser + + convert to C by dualamd +*/ + +#include +#include +#include + + +enum Colour +{ + blue = 0, + red = 1, + yellow = 2, + Invalid = 3 +}; + +const char* ColourName[] = {"blue", "red", "yellow"}; +const int STACK_SIZE = 32*1024; + +typedef unsigned int BOOL; +const BOOL TRUE = 1; +const BOOL FALSE = 0; + +int CreatureID = 0; + + +enum Colour doCompliment(enum Colour c1, enum Colour c2) +{ + switch (c1) + { + case blue: + switch (c2) + { + case blue: + return blue; + case red: + return yellow; + case yellow: + return red; + default: + goto errlb; + } + case red: + switch (c2) + { + case blue: + return yellow; + case red: + return red; + case yellow: + return blue; + default: + goto errlb; + } + case yellow: + switch (c2) + { + case blue: + return red; + case red: + return blue; + case yellow: + return yellow; + default: + goto errlb; + } + default: + break; + } + +errlb: + printf("Invalid colour\n"); + exit( 1 ); +} + +/* convert integer to number string: 1234 -> "one two three four" */ +char* formatNumber(int n, char* outbuf) +{ + int ochar = 0, ichar = 0; + int i; + char tmp[64]; + + const char* NUMBERS[] = + { + "zero", "one", "two", "three", "four", "five", + "six", "seven", "eight", "nine" + }; + + ichar = sprintf(tmp, "%d", n); + + for (i = 0; i < ichar; i++) + ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] ); + + return outbuf; +} + + +struct MeetingPlace +{ + pthread_mutex_t mutex; + int meetingsLeft; + struct Creature* firstCreature; +}; + +struct Creature +{ + pthread_t ht; + pthread_attr_t stack_att; + + struct MeetingPlace* place; + int count; + int sameCount; + + enum Colour colour; + int id; + + BOOL two_met; + BOOL sameid; +}; + + +void MeetingPlace_Init(struct MeetingPlace* m, int meetings ) +{ + pthread_mutex_init( &m->mutex, 0 ); + m->meetingsLeft = meetings; + m->firstCreature = 0; +} + + +BOOL Meet( struct Creature* cr) +{ + BOOL retval = TRUE; + + struct MeetingPlace* mp = cr->place; + pthread_mutex_lock( &(mp->mutex) ); + + if ( mp->meetingsLeft > 0 ) + { + if ( mp->firstCreature == 0 ) + { + cr->two_met = FALSE; + mp->firstCreature = cr; + } + else + { + struct Creature* first; + enum Colour newColour; + + first = mp->firstCreature; + newColour = doCompliment( cr->colour, first->colour ); + + cr->sameid = cr->id == first->id; + cr->colour = newColour; + cr->two_met = TRUE; + + first->sameid = cr->sameid; + first->colour = newColour; + first->two_met = TRUE; + + mp->firstCreature = 0; + mp->meetingsLeft--; + } + } + else + retval = FALSE; + + pthread_mutex_unlock( &(mp->mutex) ); + return retval; +} + + +void* CreatureThreadRun(void* param) +{ + struct Creature* cr = (struct Creature*)param; + + while (TRUE) + { + if ( Meet(cr) ) + { + while (cr->two_met == FALSE) + sched_yield(); + + if (cr->sameid) + cr->sameCount++; + cr->count++; + } + else + break; + } + + return 0; +} + +void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour ) +{ + cr->place = place; + cr->count = cr->sameCount = 0; + + cr->id = ++CreatureID; + cr->colour = colour; + cr->two_met = FALSE; + + pthread_attr_init( &cr->stack_att ); + pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE ); + pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) ); +} + +/* format meeting times of each creature to string */ +char* Creature_getResult(struct Creature* cr, char* str) +{ + char numstr[256]; + formatNumber(cr->sameCount, numstr); + + sprintf( str, "%u%s", cr->count, numstr ); + return str; +} + + +void runGame( int n_meeting, int ncolor, const enum Colour* colours ) +{ + int i; + int total = 0; + char str[256]; + + struct MeetingPlace place; + struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) ); + + MeetingPlace_Init( &place, n_meeting ); + + /* print initial color of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s ", ColourName[ colours[i] ] ); + Creature_Init( &(creatures[i]), &place, colours[i] ); + } + printf("\n"); + + /* wait for them to meet */ + for (i = 0; i < ncolor; i++) + pthread_join( creatures[i].ht, 0 ); + + /* print meeting times of each creature */ + for (i = 0; i < ncolor; i++) + { + printf( "%s\n", Creature_getResult(&(creatures[i]), str) ); + total += creatures[i].count; + } + + /* print total meeting times, should equal n_meeting */ + printf( "%s\n\n", formatNumber(total, str) ); + + /* cleaup & quit */ + pthread_mutex_destroy( &place.mutex ); + free( creatures ); +} + + +void printColours( enum Colour c1, enum Colour c2 ) +{ + printf( "%s + %s -> %s\n", + ColourName[c1], + ColourName[c2], + ColourName[doCompliment(c1, c2)] ); +} + +void printColoursTable(void) +{ + printColours(blue, blue); + printColours(blue, red); + printColours(blue, yellow); + printColours(red, blue); + printColours(red, red); + printColours(red, yellow); + printColours(yellow, blue); + printColours(yellow, red); + printColours(yellow, yellow); +} + +int main(int argc, char** argv) +{ + int n = (argc == 2) ? atoi(argv[1]) : 600; + + printColoursTable(); + printf("\n"); + + const enum Colour r1[] = { blue, red, yellow }; + const enum Colour r2[] = { blue, red, yellow, + red, yellow, blue, + red, yellow, red, blue }; + + runGame( n, sizeof(r1) / sizeof(r1[0]), r1 ); + runGame( n, sizeof(r2) / sizeof(r2[0]), r2 ); + + return 0; +} diff --git a/test/bench/chameneosredux.go b/test/bench/chameneosredux.go new file mode 100644 index 00000000000..6ca085ac7d2 --- /dev/null +++ b/test/bench/chameneosredux.go @@ -0,0 +1,202 @@ +/* +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. + */ + +package main + +import ( + "flag"; + "fmt"; + "os"; +) + +var n = flag.Int("n", 600, "count") + +type Color int + +const ( + blue Color = iota; + red; + yellow; +) + +func (c Color) String() string { + return []string{"blue", "red", "yellow"}[c] +} + +func complement(c1, c2 Color) Color { + switch c1 << 2 | c2 { + case blue << 2 | blue: + return blue + case blue << 2 | red: + return yellow + case blue << 2 | yellow: + return red + case red << 2 | blue: + return yellow + case red << 2 | red: + return red + case red << 2 | yellow: + return blue + case yellow << 2 | blue: + return red + case yellow << 2 | red: + return blue + case yellow << 2 | yellow: + return yellow + } + fmt.Println("invalid colors", c1, c2); + os.Exit(2); + return 0 +} + +func printColors(c1, c2 Color) { + fmt.Printf("%s + %s -> %s\n", c1, c2, complement(c1, c2)); +} + +func printColorTable() { + printColors(blue, blue); + printColors(blue, red); + printColors(blue, yellow); + printColors(red, blue); + printColors(red, red); + printColors(red, yellow); + printColors(yellow, blue); + printColors(yellow, red); + printColors(yellow, yellow); +} + +type Referee struct { + rendezCount int; + cham []*Chameneos; + rendez chan *Chameneos; + done chan int; +} + +func NewReferee() *Referee { + ref := new(Referee); + ref.cham = make([]*Chameneos, 0, 100); + ref.rendez = make(chan *Chameneos); + ref.done = make(chan int); + go ref.Serve(); + return ref; +} + +func (ref *Referee) Serve() { + for i := 0; i < *n; i++ { + c1 := <-ref.rendez; + c2 := <-ref.rendez; + c1.col, c2.col = complement(c1.col, c2.col), complement(c2.col, c1.col); + c1.rendez <- c2; + c2.rendez <- c1; + } + for i := 0; i < len(ref.cham); i++ { + c := <-ref.rendez; + c.rendez <- nil; + } + ref.done <- 1; +} + +func (ref *Referee) Add(ch *Chameneos) { + n := len(ref.cham); + ref.cham = ref.cham[0:n+1]; + ref.cham[n] = ch; +} + +type Chameneos struct { + index int; + col Color; + rendez chan *Chameneos; + count int; + same int; + ref *Referee; +} + +func (c *Chameneos) Init(index int, ref *Referee, col Color) *Chameneos { + c.index = index; + c.ref = ref; + c.col = col; + c.rendez = make(chan *Chameneos); + go c.Serve(); + return c; +} + +func (c *Chameneos) Serve() { + for { + c.ref.rendez <- c; + c1 := <- c.rendez; + if c1 == nil { + break + } + if c1.index == c.index { + c.same++ + } + c.count++; + } +} + +func play(ref *Referee, color []Color) { + cham := make([]Chameneos, len(color)); + for i, c := range color { + fmt.Printf("%s ", c); + ref.Add(cham[i].Init(i, ref, c)); + } + fmt.Printf("\n"); + <-ref.done; + total := 0; + for i, c := range cham { + total += c.count; + fmt.Printf("%d %s\n", c.count, say(c.same)); + } + fmt.Printf("%s\n\n", say(total)); +} + +var words = []string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"} + +func say(n int) string { + digits := fmt.Sprint(n); + s := ""; + for _, c := range digits { + s += " " + words[c-'0']; + } + return s; +} + +func main() { + flag.Parse(); + printColorTable(); + fmt.Print("\n"); + play(NewReferee(), []Color{blue, red, yellow}); + play(NewReferee(), []Color{blue, red, yellow, red, yellow, blue, red, yellow, red, blue}); +} diff --git a/test/bench/chameneosredux.txt b/test/bench/chameneosredux.txt new file mode 100644 index 00000000000..cf7147723b1 --- /dev/null +++ b/test/bench/chameneosredux.txt @@ -0,0 +1,28 @@ +blue + blue -> blue +blue + red -> yellow +blue + yellow -> red +red + blue -> yellow +red + red -> red +red + yellow -> blue +yellow + blue -> red +yellow + red -> blue +yellow + yellow -> yellow + + blue red yellow +400 zero +400 zero +400 zero + one two zero zero + + blue red yellow red yellow blue red yellow red blue +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero +120 zero + one two zero zero diff --git a/test/bench/timing.log b/test/bench/timing.log index 489144ee3e7..3df6714dfd1 100644 --- a/test/bench/timing.log +++ b/test/bench/timing.log @@ -137,3 +137,7 @@ threadring 50000000 # change wait code to do <-make(chan int) instead of time.Sleep gc threadring 28.41u 0.01s 29.35r GOMAXPROCS=4 gc threadring 112.59u 232.83s 384.72r + +chameneos 6000000 + gcc -O2 chameneosredux.c -lpthread 18.14u 276.52s 76.93r + gc chameneosredux 20.19u 0.01s 20.23r diff --git a/test/bench/timing.sh b/test/bench/timing.sh index 7ea4facf025..e88ca7e1572 100755 --- a/test/bench/timing.sh +++ b/test/bench/timing.sh @@ -126,9 +126,16 @@ threadring() { run 'gc threadring' $O.out -n 50000000 } +chameneos() { + echo 'chameneos 6000000' + run 'gcc -O2 chameneosredux.c -lpthread' a.out 6000000 +# run 'gccgo -O2 chameneosredux.go' a.out -n 6000000 # doesn't support the non-forward-decl variant + run 'gc chameneosredux' $O.out -n 6000000 +} + case $# in 0) - run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring" + run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos" ;; *) run=$*