mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 15:16:59 +08:00
293 lines
7.1 KiB
Go
293 lines
7.1 KiB
Go
// 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)
|
|
}
|
|
}
|
|
}
|