| // 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: go test -run=TestCalibrate -calibrate | |
| package big | |
| import ( | |
| "flag" | |
| "fmt" | |
| "testing" | |
| "time" | |
| ) | |
| var calibrate = flag.Bool("calibrate", false, "run calibration test") | |
| func karatsubaLoad(b *testing.B) { | |
| BenchmarkMul(b) | |
| } | |
| // measureKaratsuba returns the time to run a Karatsuba-relevant benchmark | |
| // given Karatsuba threshold th. | |
| func measureKaratsuba(th int) time.Duration { | |
| th, karatsubaThreshold = karatsubaThreshold, th | |
| res := testing.Benchmark(karatsubaLoad) | |
| karatsubaThreshold = th | |
| return time.Duration(res.NsPerOp()) | |
| } | |
| 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 | |
| Tb := measureKaratsuba(1e9) // th == 1e9 => Karatsuba multiplication disabled | |
| fmt.Printf("Tb = %10s\n", Tb) | |
| // thresholds | |
| th := 4 | |
| th1 := -1 | |
| th2 := -1 | |
| var deltaOld time.Duration | |
| for count := -1; count != 0 && th < 128; count-- { | |
| // determine Tk, the work load execution time using Karatsuba multiplication | |
| Tk := measureKaratsuba(th) | |
| // improvement over Tb | |
| delta := (Tb - Tk) * 100 / Tb | |
| fmt.Printf("th = %3d Tk = %10s %4d%%", th, Tk, delta) | |
| // determine break-even point | |
| if Tk < Tb && th1 < 0 { | |
| th1 = th | |
| fmt.Print(" break-even point") | |
| } | |
| // determine diminishing return | |
| if 0 < delta && delta < deltaOld && th2 < 0 { | |
| th2 = th | |
| fmt.Print(" diminishing return") | |
| } | |
| deltaOld = delta | |
| fmt.Println() | |
| // trigger counter | |
| if th1 >= 0 && th2 >= 0 && count < 0 { | |
| count = 10 // this many extra measurements after we got both thresholds | |
| } | |
| th++ | |
| } | |
| } | |
| func TestCalibrate(t *testing.T) { | |
| if *calibrate { | |
| computeThresholds() | |
| } | |
| } |