| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // This file prints execution times for the Mul benchmark | |
| // given different Karatsuba thresholds. The result may be | |
| // used to manually fine-tune the threshold constant. The | |
| // results are somewhat fragile; use repeated runs to get | |
| // a clear picture. | |
| // Usage: gotest -calibrate | |
| package big | |
| import ( | |
| "flag" | |
| "fmt" | |
| "testing" | |
| "time" | |
| ) | |
| var calibrate = flag.Bool("calibrate", false, "run calibration test") | |
| // measure returns the time to run f | |
| func measure(f func()) int64 { | |
| const N = 100 | |
| start := time.Nanoseconds() | |
| for i := N; i > 0; i-- { | |
| f() | |
| } | |
| stop := time.Nanoseconds() | |
| return (stop - start) / N | |
| } | |
| func computeThresholds() { | |
| fmt.Printf("Multiplication times for varying Karatsuba thresholds\n") | |
| fmt.Printf("(run repeatedly for good results)\n") | |
| // determine Tk, the work load execution time using basic multiplication | |
| karatsubaThreshold = 1e9 // disable karatsuba | |
| Tb := measure(benchmarkMulLoad) | |
| fmt.Printf("Tb = %dns\n", Tb) | |
| // thresholds | |
| n := 8 // any lower values for the threshold lead to very slow multiplies | |
| th1 := -1 | |
| th2 := -1 | |
| var deltaOld int64 | |
| for count := -1; count != 0; count-- { | |
| // determine Tk, the work load execution time using Karatsuba multiplication | |
| karatsubaThreshold = n // enable karatsuba | |
| Tk := measure(benchmarkMulLoad) | |
| // improvement over Tb | |
| delta := (Tb - Tk) * 100 / Tb | |
| fmt.Printf("n = %3d Tk = %8dns %4d%%", n, Tk, delta) | |
| // determine break-even point | |
| if Tk < Tb && th1 < 0 { | |
| th1 = n | |
| fmt.Print(" break-even point") | |
| } | |
| // determine diminishing return | |
| if 0 < delta && delta < deltaOld && th2 < 0 { | |
| th2 = n | |
| fmt.Print(" diminishing return") | |
| } | |
| deltaOld = delta | |
| fmt.Println() | |
| // trigger counter | |
| if th1 >= 0 && th2 >= 0 && count < 0 { | |
| count = 20 // this many extra measurements after we got both thresholds | |
| } | |
| n++ | |
| } | |
| } | |
| func TestCalibrate(t *testing.T) { | |
| if *calibrate { | |
| computeThresholds() | |
| } | |
| } |