// Copyright 2014 The Gonum Authors. All rights reserved. // Use of this code is governed by a BSD-style // license that can be found in the LICENSE file // Script for automatic code generation of the benchmark routines package main import ( "fmt" "os" "os/exec" "path" "path/filepath" "strconv" ) var gopath string var copyrightnotice = []byte(`// Copyright 2014 The Gonum Authors. All rights reserved. // Use of this code is governed by a BSD-style // license that can be found in the LICENSE file`) var autogen = []byte("// Code generated by \"go run gonum.org/v1/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go\"; DO NOT EDIT.\n") var imports = []byte(`import( "math/rand" "testing" "gonum.org/v1/gonum/blas" )`) var randomSliceFunction = []byte(`func randomSlice(l, idx int) ([]float64) { if idx < 0{ idx = -idx } s := make([]float64, l * idx) for i := range s { s[i] = rand.Float64() } return s }`) const ( posInc1 = 5 posInc2 = 3 negInc1 = -3 negInc2 = -4 ) var level1Sizes = []struct { lower string upper string camel string size int }{ { lower: "small", upper: "SMALL_SLICE", camel: "Small", size: 10, }, { lower: "medium", upper: "MEDIUM_SLICE", camel: "Medium", size: 1000, }, { lower: "large", upper: "LARGE_SLICE", camel: "Large", size: 100000, }, { lower: "huge", upper: "HUGE_SLICE", camel: "Huge", size: 10000000, }, } type level1functionStruct struct { camel string sig string call string extraSetup string oneInput bool extraName string // if have a couple different cases for the same function } var level1Functions = []level1functionStruct{ { camel: "Ddot", sig: "n int, x []float64, incX int, y []float64, incY int", call: "n, x, incX, y, incY", oneInput: false, }, { camel: "Dnrm2", sig: "n int, x []float64, incX int", call: "n, x, incX", oneInput: true, }, { camel: "Dasum", sig: "n int, x []float64, incX int", call: "n, x, incX", oneInput: true, }, { camel: "Idamax", sig: "n int, x []float64, incX int", call: "n, x, incX", oneInput: true, }, { camel: "Dswap", sig: "n int, x []float64, incX int, y []float64, incY int", call: "n, x, incX, y, incY", oneInput: false, }, { camel: "Dcopy", sig: "n int, x []float64, incX int, y []float64, incY int", call: "n, x, incX, y, incY", oneInput: false, }, { camel: "Daxpy", sig: "n int, alpha float64, x []float64, incX int, y []float64, incY int", call: "n, alpha, x, incX, y, incY", extraSetup: "alpha := 2.4", oneInput: false, }, { camel: "Drot", sig: "n int, x []float64, incX int, y []float64, incY int, c, s float64", call: "n, x, incX, y, incY, c, s", extraSetup: "c := 0.89725836967\ns:= 0.44150585279", oneInput: false, }, { camel: "Drotm", sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", call: "n, x, incX, y, incY, p", extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375,0}}", oneInput: false, extraName: "OffDia", }, { camel: "Drotm", sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", call: "n, x, incX, y, incY, p", extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}}", oneInput: false, extraName: "Dia", }, { camel: "Drotm", sig: "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams", call: "n, x, incX, y, incY, p", extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}}", oneInput: false, extraName: "Resc", }, { camel: "Dscal", sig: "n int, alpha float64, x []float64, incX int", call: "n, alpha, x, incX", extraSetup: "alpha := 2.4", oneInput: true, }, } func init() { gopath = os.Getenv("GOPATH") if gopath == "" { panic("gopath not set") } } func main() { blasPath := filepath.Join(gopath, "src", "gonum.org", "v1", "gonum", "blas") pkgs := []struct{ name string }{{name: "native"}, {name: "cgo"}} for _, pkg := range pkgs { err := level1(filepath.Join(blasPath, pkg.name), pkg.name) if err != nil { fmt.Println(err) os.Exit(1) } err = exec.Command("go", "fmt", path.Join("gonum.org", "v1", "gonum", "blas", pkg.name)).Run() if err != nil { fmt.Println(err) os.Exit(1) } } } func printHeader(f *os.File, name string) error { if _, err := f.Write(autogen); err != nil { return err } f.WriteString("\n\n") f.Write(copyrightnotice) f.WriteString("\n\n") f.WriteString("package " + name) f.WriteString("\n\n") f.Write(imports) f.WriteString("\n\n") return nil } // Generate the benchmark scripts for level1 func level1(benchPath string, pkgname string) error { // Generate level 1 benchmarks level1Filepath := filepath.Join(benchPath, "level1doubleBench_auto_test.go") f, err := os.Create(level1Filepath) if err != nil { fmt.Println(err) os.Exit(1) } defer f.Close() printHeader(f, pkgname) // Print all of the constants f.WriteString("const (\n") f.WriteString("\tposInc1 = " + strconv.Itoa(posInc1) + "\n") f.WriteString("\tposInc2 = " + strconv.Itoa(posInc2) + "\n") f.WriteString("\tnegInc1 = " + strconv.Itoa(negInc1) + "\n") f.WriteString("\tnegInc2 = " + strconv.Itoa(negInc2) + "\n") for _, con := range level1Sizes { f.WriteString("\t" + con.upper + " = " + strconv.Itoa(con.size) + "\n") } f.WriteString(")\n") f.WriteString("\n") // Write the randomSlice function f.Write(randomSliceFunction) f.WriteString("\n\n") // Start writing the benchmarks for _, fun := range level1Functions { writeLevel1Benchmark(fun, f) f.WriteString("\n/* ------------------ */ \n") } return nil } func writeLevel1Benchmark(fun level1functionStruct, f *os.File) { // First, write the base benchmark file f.WriteString("func benchmark" + fun.camel + fun.extraName + "(b *testing.B, ") f.WriteString(fun.sig) f.WriteString(") {\n") f.WriteString("b.ResetTimer()\n") f.WriteString("for i := 0; i < b.N; i++{\n") f.WriteString("\timpl." + fun.camel + "(") f.WriteString(fun.call) f.WriteString(")\n}\n}\n") f.WriteString("\n") // Write all of the benchmarks to call it for _, sz := range level1Sizes { lambda := func(incX, incY, name string, twoInput bool) { f.WriteString("func Benchmark" + fun.camel + fun.extraName + sz.camel + name + "(b *testing.B){\n") f.WriteString("n := " + sz.upper + "\n") f.WriteString("incX := " + incX + "\n") f.WriteString("x := randomSlice(n, incX)\n") if twoInput { f.WriteString("incY := " + incY + "\n") f.WriteString("y := randomSlice(n, incY)\n") } f.WriteString(fun.extraSetup + "\n") f.WriteString("benchmark" + fun.camel + fun.extraName + "(b, " + fun.call + ")\n") f.WriteString("}\n\n") } if fun.oneInput { lambda("1", "", "UnitaryInc", false) lambda("posInc1", "", "PosInc", false) } else { lambda("1", "1", "BothUnitary", true) lambda("posInc1", "1", "IncUni", true) lambda("1", "negInc1", "UniInc", true) lambda("posInc1", "negInc1", "BothInc", true) } } }