github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/blas/testblas/benchautogen/autogen_bench_level1double.go (about)

     1  // Copyright ©2014 The Gonum Authors. All rights reserved.
     2  // Use of this code is governed by a BSD-style
     3  // license that can be found in the LICENSE file
     4  
     5  // Script for automatic code generation of the benchmark routines.
     6  package main
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"strconv"
    14  )
    15  
    16  var gopath string
    17  
    18  var copyrightnotice = []byte(`// Copyright ©2014 The Gonum Authors. All rights reserved.
    19  // Use of this code is governed by a BSD-style
    20  // license that can be found in the LICENSE file`)
    21  
    22  var autogen = []byte("// Code generated by \"go run $GOPATH/src/github.com/jingcheng-WU/gonum/blas/testblas/benchautogen/autogen_bench_level1double.go\"; DO NOT EDIT.\n")
    23  
    24  var imports = []byte(`import(
    25  	"testing"
    26  
    27  	"golang.org/x/exp/rand"
    28  
    29  	"github.com/jingcheng-WU/gonum/blas"
    30  )`)
    31  
    32  var randomSliceFunction = []byte(`func randomSlice(l, idx int) ([]float64) {
    33  	if idx < 0{
    34  		idx = -idx
    35  	}
    36  	s := make([]float64, l * idx)
    37  	for i := range s {
    38  		s[i] = rand.Float64()
    39  	}
    40  	return s
    41  }`)
    42  
    43  const (
    44  	posInc1 = 5
    45  	posInc2 = 3
    46  	negInc1 = -3
    47  	negInc2 = -4
    48  )
    49  
    50  var level1Sizes = []struct {
    51  	lower string
    52  	upper string
    53  	camel string
    54  	size  int
    55  }{
    56  	{
    57  		lower: "small",
    58  		upper: "SMALL_SLICE",
    59  		camel: "Small",
    60  		size:  10,
    61  	},
    62  	{
    63  		lower: "medium",
    64  		upper: "MEDIUM_SLICE",
    65  		camel: "Medium",
    66  		size:  1000,
    67  	},
    68  	{
    69  		lower: "large",
    70  		upper: "LARGE_SLICE",
    71  		camel: "Large",
    72  		size:  100000,
    73  	},
    74  	{
    75  		lower: "huge",
    76  		upper: "HUGE_SLICE",
    77  		camel: "Huge",
    78  		size:  10000000,
    79  	},
    80  }
    81  
    82  type level1functionStruct struct {
    83  	camel      string
    84  	sig        string
    85  	call       string
    86  	extraSetup string
    87  	oneInput   bool
    88  	extraName  string // if have a couple different cases for the same function
    89  }
    90  
    91  var level1Functions = []level1functionStruct{
    92  	{
    93  		camel:    "Ddot",
    94  		sig:      "n int, x []float64, incX int, y []float64, incY int",
    95  		call:     "n, x, incX, y, incY",
    96  		oneInput: false,
    97  	},
    98  	{
    99  		camel:    "Dnrm2",
   100  		sig:      "n int, x []float64, incX int",
   101  		call:     "n, x, incX",
   102  		oneInput: true,
   103  	},
   104  	{
   105  		camel:    "Dasum",
   106  		sig:      "n int, x []float64, incX int",
   107  		call:     "n, x, incX",
   108  		oneInput: true,
   109  	},
   110  	{
   111  		camel:    "Idamax",
   112  		sig:      "n int, x []float64, incX int",
   113  		call:     "n, x, incX",
   114  		oneInput: true,
   115  	},
   116  	{
   117  		camel:    "Dswap",
   118  		sig:      "n int, x []float64, incX int, y []float64, incY int",
   119  		call:     "n, x, incX, y, incY",
   120  		oneInput: false,
   121  	},
   122  	{
   123  		camel:    "Dcopy",
   124  		sig:      "n int, x []float64, incX int, y []float64, incY int",
   125  		call:     "n, x, incX, y, incY",
   126  		oneInput: false,
   127  	},
   128  	{
   129  		camel:      "Daxpy",
   130  		sig:        "n int, alpha float64, x []float64, incX int, y []float64, incY int",
   131  		call:       "n, alpha, x, incX, y, incY",
   132  		extraSetup: "alpha := 2.4",
   133  		oneInput:   false,
   134  	},
   135  	{
   136  		camel:      "Drot",
   137  		sig:        "n int, x []float64, incX int, y []float64, incY int, c, s float64",
   138  		call:       "n, x, incX, y, incY, c, s",
   139  		extraSetup: "c := 0.89725836967\ns:= 0.44150585279",
   140  		oneInput:   false,
   141  	},
   142  	{
   143  		camel:      "Drotm",
   144  		sig:        "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams",
   145  		call:       "n, x, incX, y, incY, p",
   146  		extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{0, -0.625, 0.9375,0}}",
   147  		oneInput:   false,
   148  		extraName:  "OffDia",
   149  	},
   150  	{
   151  		camel:      "Drotm",
   152  		sig:        "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams",
   153  		call:       "n, x, incX, y, incY, p",
   154  		extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{5.0 / 12, 0, 0, 0.625}}",
   155  		oneInput:   false,
   156  		extraName:  "Dia",
   157  	},
   158  	{
   159  		camel:      "Drotm",
   160  		sig:        "n int, x []float64, incX int, y []float64, incY int, p blas.DrotmParams",
   161  		call:       "n, x, incX, y, incY, p",
   162  		extraSetup: "p := blas.DrotmParams{Flag: blas.OffDiagonal, H: [4]float64{4096, -3584, 1792, 4096}}",
   163  		oneInput:   false,
   164  		extraName:  "Resc",
   165  	},
   166  	{
   167  		camel:      "Dscal",
   168  		sig:        "n int, alpha float64, x []float64, incX int",
   169  		call:       "n, alpha, x, incX",
   170  		extraSetup: "alpha := 2.4",
   171  		oneInput:   true,
   172  	},
   173  }
   174  
   175  func init() {
   176  	gopath = os.Getenv("GOPATH")
   177  	if gopath == "" {
   178  		panic("gopath not set")
   179  	}
   180  }
   181  
   182  func main() {
   183  	pkgs := []string{"gonum", "netlib"}
   184  	for _, pkg := range pkgs {
   185  		blasPath := filepath.Join(gopath, "src", "gonum.org", "v1", pkg, "blas", pkg)
   186  		err := level1(blasPath, pkg)
   187  		if err != nil {
   188  			fmt.Println(err)
   189  			os.Exit(1)
   190  		}
   191  
   192  		err = exec.Command("goimports", "-w", blasPath).Run()
   193  		if err != nil {
   194  			fmt.Println(err)
   195  			os.Exit(1)
   196  		}
   197  	}
   198  }
   199  
   200  func printHeader(f errFile, name string) {
   201  	f.Write(autogen)
   202  	f.WriteString("\n\n")
   203  	f.Write(copyrightnotice)
   204  	f.WriteString("\n\n")
   205  	f.WriteString("package " + name)
   206  	f.WriteString("\n\n")
   207  	f.Write(imports)
   208  	f.WriteString("\n\n")
   209  }
   210  
   211  // Generate the benchmark scripts for level1
   212  func level1(benchPath string, pkgname string) error {
   213  	// Generate level 1 benchmarks
   214  	level1Filepath := filepath.Join(benchPath, "level1float64_bench_test.go")
   215  	var f errFile
   216  	f.file, f.err = os.Create(level1Filepath)
   217  	if f.err != nil {
   218  		return f.err
   219  	}
   220  	defer f.file.Close()
   221  
   222  	printHeader(f, pkgname)
   223  
   224  	// Print all of the constants
   225  	f.WriteString("const (\n")
   226  	f.WriteString("\tposInc1 = " + strconv.Itoa(posInc1) + "\n")
   227  	f.WriteString("\tposInc2 = " + strconv.Itoa(posInc2) + "\n")
   228  	f.WriteString("\tnegInc1 = " + strconv.Itoa(negInc1) + "\n")
   229  	f.WriteString("\tnegInc2 = " + strconv.Itoa(negInc2) + "\n")
   230  	for _, con := range level1Sizes {
   231  		f.WriteString("\t" + con.upper + " = " + strconv.Itoa(con.size) + "\n")
   232  	}
   233  	f.WriteString(")\n")
   234  	f.WriteString("\n")
   235  
   236  	// Write the randomSlice function
   237  	f.Write(randomSliceFunction)
   238  	f.WriteString("\n\n")
   239  
   240  	// Start writing the benchmarks
   241  	for _, fun := range level1Functions {
   242  		writeLevel1Benchmark(fun, f)
   243  		f.WriteString("\n/* ------------------ */ \n")
   244  	}
   245  
   246  	return f.err
   247  }
   248  
   249  func writeLevel1Benchmark(fun level1functionStruct, f errFile) {
   250  	// First, write the base benchmark file
   251  	f.WriteString("func benchmark" + fun.camel + fun.extraName + "(b *testing.B, ")
   252  	f.WriteString(fun.sig)
   253  	f.WriteString(") {\n")
   254  
   255  	f.WriteString("b.ResetTimer()\n")
   256  	f.WriteString("for i := 0; i < b.N; i++{\n")
   257  	f.WriteString("\timpl." + fun.camel + "(")
   258  
   259  	f.WriteString(fun.call)
   260  	f.WriteString(")\n}\n}\n")
   261  	f.WriteString("\n")
   262  
   263  	// Write all of the benchmarks to call it
   264  	for _, sz := range level1Sizes {
   265  		lambda := func(incX, incY, name string, twoInput bool) {
   266  			f.WriteString("func Benchmark" + fun.camel + fun.extraName + sz.camel + name + "(b *testing.B){\n")
   267  			f.WriteString("n := " + sz.upper + "\n")
   268  			f.WriteString("incX := " + incX + "\n")
   269  			f.WriteString("x := randomSlice(n, incX)\n")
   270  			if twoInput {
   271  				f.WriteString("incY := " + incY + "\n")
   272  				f.WriteString("y := randomSlice(n, incY)\n")
   273  			}
   274  			f.WriteString(fun.extraSetup + "\n")
   275  			f.WriteString("benchmark" + fun.camel + fun.extraName + "(b, " + fun.call + ")\n")
   276  			f.WriteString("}\n\n")
   277  		}
   278  		if fun.oneInput {
   279  			lambda("1", "", "UnitaryInc", false)
   280  			lambda("posInc1", "", "PosInc", false)
   281  		} else {
   282  			lambda("1", "1", "BothUnitary", true)
   283  			lambda("posInc1", "1", "IncUni", true)
   284  			lambda("1", "negInc1", "UniInc", true)
   285  			lambda("posInc1", "negInc1", "BothInc", true)
   286  		}
   287  	}
   288  }
   289  
   290  type errFile struct {
   291  	file *os.File
   292  	err  error
   293  }
   294  
   295  func (f errFile) Write(b []byte) {
   296  	if f.err != nil {
   297  		return
   298  	}
   299  	_, f.err = f.file.Write(b)
   300  }
   301  
   302  func (f errFile) WriteString(s string) {
   303  	if f.err != nil {
   304  		return
   305  	}
   306  	_, f.err = f.file.WriteString(s)
   307  }