]> Cypherpunks repositories - gostls13.git/commitdiff
chameneos
authorRob Pike <r@golang.org>
Fri, 7 Aug 2009 22:28:46 +0000 (15:28 -0700)
committerRob Pike <r@golang.org>
Fri, 7 Aug 2009 22:28:46 +0000 (15:28 -0700)
R=rsc
DELTA=514  (513 added, 0 deleted, 1 changed)
OCL=32898
CL=32910

test/bench/chameneosredux.c [new file with mode: 0644]
test/bench/chameneosredux.go [new file with mode: 0644]
test/bench/chameneosredux.txt [new file with mode: 0644]
test/bench/timing.log
test/bench/timing.sh

diff --git a/test/bench/chameneosredux.c b/test/bench/chameneosredux.c
new file mode 100644 (file)
index 0000000..ed78c31
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+
+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 (file)
index 0000000..6ca085a
--- /dev/null
@@ -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 (file)
index 0000000..cf71477
--- /dev/null
@@ -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
index 489144ee3e7c0e98fd22b61439d7291bd469ae94..3df6714dfd1581f59638c56ab75059453e1d64b1 100644 (file)
@@ -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
index 7ea4facf025708038cdd72c980fb5bae05677537..e88ca7e1572fd42ce631c99e3b0ab7f7f5e6bad8 100755 (executable)
@@ -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=$*