Home | History | Annotate | Download | only in big
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // This file prints execution times for the Mul benchmark
      6 // given different Karatsuba thresholds. The result may be
      7 // used to manually fine-tune the threshold constant. The
      8 // results are somewhat fragile; use repeated runs to get
      9 // a clear picture.
     10 
     11 // Usage: go test -run=TestCalibrate -calibrate
     12 
     13 package big
     14 
     15 import (
     16 	"flag"
     17 	"fmt"
     18 	"testing"
     19 	"time"
     20 )
     21 
     22 var calibrate = flag.Bool("calibrate", false, "run calibration test")
     23 
     24 func karatsubaLoad(b *testing.B) {
     25 	BenchmarkMul(b)
     26 }
     27 
     28 // measureKaratsuba returns the time to run a Karatsuba-relevant benchmark
     29 // given Karatsuba threshold th.
     30 func measureKaratsuba(th int) time.Duration {
     31 	th, karatsubaThreshold = karatsubaThreshold, th
     32 	res := testing.Benchmark(karatsubaLoad)
     33 	karatsubaThreshold = th
     34 	return time.Duration(res.NsPerOp())
     35 }
     36 
     37 func computeThresholds() {
     38 	fmt.Printf("Multiplication times for varying Karatsuba thresholds\n")
     39 	fmt.Printf("(run repeatedly for good results)\n")
     40 
     41 	// determine Tk, the work load execution time using basic multiplication
     42 	Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled
     43 	fmt.Printf("Tb = %10s\n", Tb)
     44 
     45 	// thresholds
     46 	th := 4
     47 	th1 := -1
     48 	th2 := -1
     49 
     50 	var deltaOld time.Duration
     51 	for count := -1; count != 0 && th < 128; count-- {
     52 		// determine Tk, the work load execution time using Karatsuba multiplication
     53 		Tk := measureKaratsuba(th)
     54 
     55 		// improvement over Tb
     56 		delta := (Tb - Tk) * 100 / Tb
     57 
     58 		fmt.Printf("th = %3d  Tk = %10s  %4d%%", th, Tk, delta)
     59 
     60 		// determine break-even point
     61 		if Tk < Tb && th1 < 0 {
     62 			th1 = th
     63 			fmt.Print("  break-even point")
     64 		}
     65 
     66 		// determine diminishing return
     67 		if 0 < delta && delta < deltaOld && th2 < 0 {
     68 			th2 = th
     69 			fmt.Print("  diminishing return")
     70 		}
     71 		deltaOld = delta
     72 
     73 		fmt.Println()
     74 
     75 		// trigger counter
     76 		if th1 >= 0 && th2 >= 0 && count < 0 {
     77 			count = 10 // this many extra measurements after we got both thresholds
     78 		}
     79 
     80 		th++
     81 	}
     82 }
     83 
     84 func TestCalibrate(t *testing.T) {
     85 	if *calibrate {
     86 		computeThresholds()
     87 	}
     88 }
     89