### CUDA Test Program Output Example Source: https://gorgonia.org/cu Example output from the `cudatest` program, showing detected CUDA version and device details. This confirms successful CUDA setup. ```text CUDA version: 10020 CUDA devices: 1 Device 0 ======== Name : "TITAN RTX" Clock Rate: 1770000 kHz Memory : 25393561600 bytes Compute : 7.5 ``` -------------------------------- ### Install Gorgonia Source: https://gorgonia.org/getting-started Use this command to get the Gorgonia library and its dependencies. ```bash $ go get gorgonia.org/gorgonia ``` -------------------------------- ### CLI utility output example Source: https://gorgonia.org/tutorials/iris Example output format for the final CLI utility. ```text ./iris sepal length: 5 sepal width: 3.5 petal length: 1.4 sepal length: 0.2 It is probably a setosa ``` -------------------------------- ### Install CUDA Binding and Generate Source: https://gorgonia.org/tutorials/mnist-cuda Set GO111MODULE to off, install Gorgonia and the CUDA binding tool, and then generate the CUDA binding for your hardware. Ensure CUDA toolkit is in your PATH. ```bash ~ export GO111MODULE=off ~ go get gorgonia.org/gorgonia ~ export CGO_CFLAGS="-I/usr/local/cuda-10.0/include/" ~ export PATH=$PATH:/usr/local/cuda/bin/ ~ go get gorgonia.org/cu ~ go install gorgonia.org/gorgonia/cmd/cudagen ~ $GOPATH/bin/cudagen ``` -------------------------------- ### Install and Run CUDA Test Program Source: https://gorgonia.org/cu Installs the `cudatest` utility and runs it to verify CUDA installation and device detection. Ensure CUDA Toolkit is installed and configured. ```bash go install gorgonia.org/cu/cmd/cudatest@latest cudatest ``` -------------------------------- ### Example execution output Source: https://gorgonia.org/tutorials/hello-world Shows the expected output when the complete Go program is executed. ```Shell $ go run main.go 4.5 ``` -------------------------------- ### Install vecf64 Package Source: https://gorgonia.org/vecf64 Use this command to install the vecf64 package. It only uses the standard library. ```bash go get -u gorgonia.org/vecf64 ``` -------------------------------- ### String and Integer Addition Examples Source: https://gorgonia.org/dtype Demonstrates the concept of 'addition' for both string and integer types, illustrating their inclusion in an 'Addable' type class. ```Go // string "addition". s := "hello" s += "world" // int addition. i := 1 i += 1 ``` -------------------------------- ### Generate SVG Graph from Dot Output Source: https://gorgonia.org/how-to/dot This command-line example shows how to pipe the output of the Go program into the `dot` command to generate an SVG image of the graph. Make sure Graphviz is installed. ```bash $ go run main.go | dot -Tsvg > dot-example.svg ``` -------------------------------- ### Compute float32 addition with Gorgonia Source: https://gorgonia.org/reference/vm/gomachine A complete example demonstrating graph creation, scalar definition, machine execution, and result retrieval. ```go func main(){ g := gorgonia.NewGraph() forty := gorgonia.F32(40.0) two := gorgonia.F32(2.0) n1 := gorgonia.NewScalar(g, gorgonia.Float32, gorgonia.WithValue(&forty), gorgonia.WithName("n1")) n2 := gorgonia.NewScalar(g, gorgonia.Float32, gorgonia.WithValue(&two), gorgonia.WithName("n2")) added, err := gorgonia.Add(n1, n2) if err != nil { log.Fatal(err) } machine := NewMachine(g) ctx, cancel := context.WithTimeout(context.Background(), 1000*time.Millisecond) defer cancel() defer machine.Close() err = machine.Run(ctx) if err != nil { log.Fatal(err) } fmt.Println(machine.GetResult(added.ID())) } ``` -------------------------------- ### Execution Output Source: https://gorgonia.org/how-to/save-weights Shows the console output when running the backup/restore example for the first time and subsequent times. ```bash $ go run main.go 2019/10/28 08:07:26 cannot read backup, doing init open /tmp/example_gorgonia: no such file or directory ⎡0 2⎤ ⎣4 6⎦ $ go run main.go 2019/10/28 08:07:29 decoding xT 2019/10/28 08:07:29 decoding yT ⎡0 2⎤ ⎣4 6⎦ ``` -------------------------------- ### Install cudatest Source: https://gorgonia.org/how-to/troubleshoot-gpu-issues Installs the `cudatest` utility for troubleshooting CUDA issues. Ensure you have CUDA and cuDNN installed prior to running this command. ```bash go install gorgonia.org/cu/cmd/cudatest ``` -------------------------------- ### Run CUDA-enabled Convnet Example Source: https://gorgonia.org/tutorials/mnist-cuda Execute the convnet example with CUDA support enabled using the '-tags="CUDA"' flag. This command times the execution and redirects stderr to null. ```bash time go run -tags='CUDA' main.go -epochs 1 2> /dev/null Epoch 0 599 / 600 [====================================================] 99.83% ``` -------------------------------- ### Node Communication Example Source: https://gorgonia.org/reference/vm/gomachine Illustrates how nodes in a computation graph are wired together using channels for communication. This example shows sending values between nodes for operations like multiplication and addition. ```go var aTimesX *node{op: mul} var aTimesXPlusB *node{op: sum} var a,b,c gorgonia.Value aTimesX.inputC <- a aTimesX.inputC <- x aTimesXPlusB.inputC <- <- aTimesX.outputC aTimesXPlusB.inputC <- <- b ``` -------------------------------- ### Install cudagen Tool Source: https://gorgonia.org/reference/cuda Install the `cudagen` utility, which is necessary for generating CUDA-related code for Gorgonia. This tool is part of the Gorgonia project. ```bash go install gorgonia.org/gorgonia/cmd/cudagen ``` -------------------------------- ### Build Gorgonia with CUDA Support Source: https://gorgonia.org/reference/cuda To enable CUDA support, build your Go application using the 'cuda' build tag. Ensure the CUDA toolkit is installed and `cudagen` is available. ```bash go build -tags='cuda' . ``` -------------------------------- ### Primitive Shape Construction Examples Source: https://gorgonia.org/shapes Demonstrates the primitive ways to construct shapes according to the BNF, including unit, integer-based, and variable-based shapes. ```text () // unit (10,) // integer-based shape (8, (10,)) // nested integer-based shape ((8, (10,)), 20) // deeply nested integer-based shape ``` -------------------------------- ### Run MNIST Example Source: https://gorgonia.org/tutorials/mnist Executes the main program to output the label vector for the processed image. ```bash $ go run main.go [0.1 0.1 0.1 0.1 0.1 0.9 0.1 0.1 0.1 0.1] ``` -------------------------------- ### Computation output Source: https://gorgonia.org/reference/vm/gomachine The expected output of the float32 addition example. ```text 42 ``` -------------------------------- ### Implement state function context handling Source: https://gorgonia.org/reference/vm/gomachine Example of handling context cancellation within a state function. ```go func mystate(ctx context.Context, *node) stateFn { // ... select { // ... case <- ctx.Done(): n.err = ctx.Error() return nil } } ``` -------------------------------- ### Tensor Data Type Mismatch Example Source: https://gorgonia.org/tensor This example demonstrates a panic that occurs when attempting to set data of an incorrect type to a tensor. Ensure the data type passed to `SetAt` matches the tensor's underlying data type. ```go b := New(WithBacking(Range(Float32, 0, 24)), WithShape(2, 3, 4)) x, _ := b.At(0, 1, 2) fmt.Printf("x: %v\n", x) // Setting data b.SetAt(1000, 0, 1, 2) fmt.Printf("b:\n%v", b) ``` -------------------------------- ### Evolving Shape Constraints Source: https://gorgonia.org/shapes Example of applying a shape expression to a known input to evolve constraints. ```text (a, b) → (b, c) → (a, c) @ (2, 3) ``` ```text (3, c) → (2, c) ``` -------------------------------- ### Helper Function to Get User Input Source: https://gorgonia.org/tutorials/iris A utility function to prompt the user for input, read a line from stdin, and parse it as a float64. Handles newline characters and potential parsing errors. ```go func getInput(s string) float64 { reader := bufio.NewReader(os.Stdin) fmt.Printf("%v: ", s) text, _ := reader.ReadString('\n') text = strings.Replace(text, "\n", "", -1) input, err := strconv.ParseFloat(text, 64) if err != nil { log.Fatal(err) } return input } ``` -------------------------------- ### Initialize Training Components Source: https://gorgonia.org/tutorials/mnist Sets up the VM, solver, and training loop structure. ```go vm := gorgonia.NewTapeMachine(g, gorgonia.BindDualValues(m.learnables()...)) solver := gorgonia.NewRMSPropSolver(gorgonia.WithBatchSize(float64(bs))) defer vm.Close() ``` ```go batches := numExamples / bs ``` ```go for i := 0; i < *epochs; i++ { for b := 0; b < batches; b++ { // ... } } ``` -------------------------------- ### Initialize Tape Machine Source: https://gorgonia.org/tutorials/iris Sets up a Tape Machine to execute the graph and compute gradients. It's crucial to bind dual values for parameters that require gradient tracking, like 'theta'. ```go machine := gorgonia.NewTapeMachine(g, gorgonia.BindDualValues(theta)) defer machine.Close() ``` -------------------------------- ### Initialize Vanilla Solver Source: https://gorgonia.org/tutorials/iris Creates a Vanilla Solver instance for gradient descent with a specified learning rate. Use this to update model parameters iteratively. ```go solver := gorgonia.NewVanillaSolver(gorgonia.WithLearnRate(0.001)) ``` -------------------------------- ### Basic Graph Creation and Execution in Gorgonia Source: https://gorgonia.org/gorgonia Demonstrates how to define a simple mathematical expression z = x + y as a computation graph, compile it into a program, and execute it using a TapeMachine. Requires manual value setting with Let. ```go package gorgonia_test import ( "fmt" "log" . "gorgonia.org/gorgonia" ) // Basic example of representing mathematical equations as graphs. // // In this example, we want to represent the following equation // z = x + y func Example_basic() { g := NewGraph() var x, y, z *Node var err error // define the expression x = NewScalar(g, Float64, WithName("x")) y = NewScalar(g, Float64, WithName("y")) if z, err = Add(x, y); err != nil { log.Fatal(err) } // create a VM to run the program on machine := NewTapeMachine(g) defer machine.Close() // set initial values then run Let(x, 2.0) Let(y, 2.5) if err = machine.RunAll(); err != nil { log.Fatal(err) } fmt.Printf("%v", z.Value()) // Output: 4.5 } ``` -------------------------------- ### Simple Computation with Gorgonia Source: https://gorgonia.org/getting-started This program demonstrates creating a computation graph, defining scalar nodes, performing addition, and executing the computation using a tape machine. Ensure you have the necessary imports. If you encounter a GC-related panic, set the environment variable `ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH=go1.19`. ```go package main import ( "fmt" "log" "gorgonia.org/gorgonia" ) func main() { g := gorgonia.NewGraph() var x, y, z *gorgonia.Node var err error // define the expression x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x")) y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y")) if z, err = gorgonia.Add(x, y); err != nil { log.Fatal(err) } // create a VM to run the program on machine := gorgonia.NewTapeMachine(g) defer machine.Close() // set initial values then run gorgonia.Let(x, 2.0) gorgonia.Let(y, 2.5) if err = machine.RunAll(); err != nil { log.Fatal(err) } fmt.Printf("%v", z.Value()) } ``` -------------------------------- ### Instantiate and run TapeMachine Source: https://gorgonia.org/tutorials/hello-world Creates a TapeMachine to execute the computation graph and runs all operations. Ensures the machine is closed afterwards using defer. ```Go machine := gorgonia.NewTapeMachine(g) defer machine.Close() if err = machine.RunAll(); err != nil { log.Fatal(err) } ``` -------------------------------- ### Gorgonia Graph Addition Source: https://gorgonia.org/about/computation-graph Demonstrates creating a computation graph, defining nodes, performing addition, and executing the graph using a TapeMachine. ```go func main() { // Create a graph. g := gorgonia.NewGraph() // Create a node called "x" with the value 1. x := gorgonia.NodeFromAny(g, 1, gorgonia.WithName("x")) // Create a node called "y" with the value 1. y := gorgonia.NodeFromAny(g, 1, gorgonia.WithName("y")) // z := x + y z := gorgonia.Must(gorgonia.Add(x, y)) // Create a VM to execute the graph. vm := gorgonia.NewTapeMachine(g) // Run the VM. Errors are not checked. vm.RunAll() // Print the value of z. fmt.Printf("%v", z.Value()) } ``` -------------------------------- ### Build with AVX Support Source: https://gorgonia.org/vecf64 To enable SIMD acceleration using AVX instructions, use this build command. ```bash go build -tags='avx' ... ``` -------------------------------- ### Execute Training Step Source: https://gorgonia.org/tutorials/mnist Extracts batch data, assigns values to the graph, and runs the solver. ```go var xVal, yVal tensor.Tensor xVal, _ = inputs.Slice(sli{start, end}) yVal, _ = targets.Slice(sli{start, end}) xVal.(*tensor.Dense).Reshape(bs, 1, 28, 28) ``` ```go gorgonia.Let(x, xVal) gorgonia.Let(y, yVal) ``` ```go vm.RunAll() solver.Step(gorgonia.NodesToValueGrads(m.learnables())) vm.Reset() ``` -------------------------------- ### Build with SSE Support Source: https://gorgonia.org/vecf64 To enable Single Instruction, Multiple Data (SIMD) acceleration using SSE instructions, use this build command. ```bash go build -tags='sse' ... ``` -------------------------------- ### Create CUDA Shared Object Symlink on Linux Source: https://gorgonia.org/cu Creates a symbolic link for `libcuda.so` on Linux systems, typically required when the CUDA shared object is installed in a non-standard location or not automatically linked by `ld`. Adjust paths as necessary. ```bash sudo ln -s /PATH/TO/libcuda.so.1 /PATH/TO/libcuda.so ``` -------------------------------- ### Create a new Gorgonia graph Source: https://gorgonia.org/tutorials/hello-world Initializes an empty expression graph. This is the first step in building any computation with Gorgonia. ```Go g := gorgonia.NewGraph() ``` -------------------------------- ### Initialize Convolutional Network Weights Source: https://gorgonia.org/tutorials/mnist Creates the network structure and initializes learnable parameters using Glorot initialization. ```go // Note: gorgonia is abbreviated G in this example for clarity func newConvNet(g *G.ExprGraph) *convnet { w0 := G.NewTensor(g, dt, 4, G.WithShape(32, 1, 3, 3), G.WithName("w0"), G.WithInit(G.GlorotN(1.0))) w1 := G.NewTensor(g, dt, 4, G.WithShape(64, 32, 3, 3), G.WithName("w1"), G.WithInit(G.GlorotN(1.0))) w2 := G.NewTensor(g, dt, 4, G.WithShape(128, 64, 3, 3), G.WithName("w2"), G.WithInit(G.GlorotN(1.0))) w3 := G.NewMatrix(g, dt, G.WithShape(128*3*3, 625), G.WithName("w3"), G.WithInit(G.GlorotN(1.0))) w4 := G.NewMatrix(g, dt, G.WithShape(625, 10), G.WithName("w4"), G.WithInit(G.GlorotN(1.0))) return &convnet{ g: g, w0: w0, w1: w1, w2: w2, w3: w3, w4: w4, d0: 0.2, d1: 0.2, d2: 0.2, d3: 0.55, } } ``` -------------------------------- ### Create a (2,2) Dense Tensor Source: https://gorgonia.org/tensor Demonstrates how to create a 2x2 dense tensor with integer backing data. Ensure the backing data matches the shape. ```go a := New(WithShape(2, 2), WithBacking([]int{1, 2, 3, 4})) fmt.Printf("a:\n%v\n", a) ``` -------------------------------- ### Instantiate Neural Network Graph Source: https://gorgonia.org/tutorials/mnist Initializes the computation graph and defines input/output nodes. ```go g := gorgonia.NewGraph() x := gorgonia.NewTensor(g, dt, 4, gorgonia.WithShape(bs, 1, 28, 28), gorgonia.WithName("x")) y := gorgonia.NewMatrix(g, dt, gorgonia.WithShape(bs, 10), gorgonia.WithName("y")) m := newConvNet(g) m.fwd(x) ``` -------------------------------- ### Standard Go Addition Source: https://gorgonia.org/about/computation-graph A basic Go program performing addition without using the Gorgonia library. ```go func main() { fmt.Printf("%v", 1+1) } ``` -------------------------------- ### Define the VM interface Source: https://gorgonia.org/reference/vm The VM interface defines the core methods required for executing and managing computational resources in Gorgonia. ```go type VM interface { RunAll() error Reset() // Close closes all the machine resources (CUDA, if any, loggers if any) Close() error } ``` -------------------------------- ### Run Prediction Loop in CLI Source: https://gorgonia.org/tutorials/iris Initializes a tape machine, sets up input processing, and runs the prediction loop. It continuously takes input, performs computation, and displays the predicted iris species. Ensure `getInput` function is defined. ```go machine := gorgonia.NewTapeMachine(g) values[4] = 1.0 for { values[0] = getInput("sepal length") values[1] = getInput("sepal width") values[2] = getInput("petal length") values[3] = getInput("petal width") if err = machine.RunAll(); err != nil { log.Fatal(err) } switch math.Round(y.Value().Data().(float64)) { case 1: fmt.Println("It is probably a setosa") case 2: fmt.Println("It is probably a virginica") case 3: fmt.Println("It is probably a versicolor") default: fmt.Println("unknown iris") } machine.Reset() } ``` -------------------------------- ### Execute with TapeMachine Source: https://gorgonia.org/how-to/autodiff Run the graph using the TapeMachine and access gradients via nodes or the Grad method. ```go machine := gorgonia.NewTapeMachine(g) defer machine.Close() if err = machine.RunAll(); err != nil { log.Fatal(err) } fmt.Printf("result: %v\n", result.Value()) if zgrad, err := z.Grad(); err == nil { fmt.Printf("dz/dx: %v | %v\n", zgrad, grads[0].Value()) } if xgrad, err := x.Grad(); err == nil { fmt.Printf("dz/dx: %v | %v\n", xgrad, grads[1].Value()) } if ygrad, err := y.Grad(); err == nil { fmt.Printf("dz/dy: %v | %v\n", ygrad, grads[2].Value()) } ``` -------------------------------- ### Create an expression graph Source: https://gorgonia.org/how-to/autodiff Initialize a new graph and define the mathematical expression f(x,y,z)=(x+y)×z. ```go g := gorgonia.NewGraph() var x, y, z *gorgonia.Node var err error // define the expression x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x")) y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y")) z = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("z")) q, err := gorgonia.Add(x, y) if err != nil { log.Fatal(err) } result, err := gorgonia.Mul(z, q) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Create Gorgonia Expression Graph Source: https://gorgonia.org/tutorials/iris Initializes a Gorgonia graph and defines nodes for input data (x, y) and model parameters (theta). Use this to represent your model's structure. ```go func getXY() (*tensor.Dense, *tensor.Dense) { x, y := getXYMat() xT := tensor.FromMat64(x) yT := tensor.FromMat64(y) // Get rid of the last dimension to create a vector s := yT.Shape() yT.Reshape(s[0]) return xT, yT } func main() { xT, yT := getXY() g := gorgonia.NewGraph() x := gorgonia.NodeFromAny(g, xT, gorgonia.WithName("x")) y := gorgonia.NodeFromAny(g, yT, gorgonia.WithName("y")) heta := gorgonia.NewVector( g, gorgonia.Float64, gorgonia.WithName("theta"), gorgonia.WithShape(xT.Shape()[1]), gorgonia.WithInit(gorgonia.Uniform(0, 1))) pred := must(gorgonia.Mul(x, theta)) // Saving the value for later use var predicted gorgonia.Value gorgonia.Read(pred, &predicted) ``` -------------------------------- ### Numerical Stability Comparison Source: https://gorgonia.org/about/computation-graph Compares standard math.Log with math.Log1p to demonstrate numerical stability issues with floating-point arithmetic. ```go func main() { fmt.Printf("%v\n", math.Log(1.0+10e-16)) fmt.Printf("%v\n", math.Log1p(10e-16)) } ``` -------------------------------- ### Print values and gradients Source: https://gorgonia.org/how-to/autodiff Display the results and partial derivatives after graph execution. ```go fmt.Printf("x=%v;y=%v;z=%v\n", x.Value(), y.Value(), z.Value()) fmt.Printf("f(x,y,z) = %v\n", result.Value()) if xgrad, err := x.Grad(); err == nil { fmt.Printf("df/dx: %v\n", xgrad) } if ygrad, err := y.Grad(); err == nil { fmt.Printf("df/dy: %v\n", ygrad) } if xgrad, err := z.Grad(); err == nil { fmt.Printf("df/dx: %v\n", xgrad) } ``` -------------------------------- ### Run Gradient Descent Iterations Source: https://gorgonia.org/tutorials/iris Executes the graph, updates model parameters using the solver, and resets the machine for the next iteration. This loop performs the core gradient descent training. ```go iter := 1000000 var err error for i := 0; i < iter; i++ { if err = machine.RunAll(); err != nil { fmt.Printf("Error during iteration: %v: %v\n", i, err) break } if err = solver.Step(model); err != nil { log.Fatal(err) } machine.Reset() // Reset is necessary in a loop like this } ``` -------------------------------- ### Generic Tensor Allocation with String Backing Source: https://gorgonia.org/tensor Demonstrates generic tensor allocation using a backing slice of strings and specifying a shape. The *Dense structure allows for runtime type flexibility. ```go x := New(WithBacking([]string{"hello", "world", "hello", "world"}), WithShape(2,2)) ``` -------------------------------- ### Display Directory Structure Source: https://gorgonia.org/tutorials/mnist Expected file layout for the MNIST test data directory. ```bash $ ls -alhg * -rw-r--r-- 1 staff 375B Nov 11 13:48 main.go testdata: total 107344 drwxr-xr-x 6 staff 192B Nov 11 13:48 . drwxr-xr-x 4 staff 128B Nov 11 13:48 .. -rw-r--r-- 1 staff 7.5M Jul 21 2000 t10k-images.idx3-ubyte -rw-r--r-- 1 staff 9.8K Jul 21 2000 t10k-labels.idx1-ubyte -rw-r--r-- 1 staff 45M Jul 21 2000 train-images.idx3-ubyte -rw-r--r-- 1 staff 59K Jul 21 2000 train-labels.idx1-ubyte ``` -------------------------------- ### Prepare Model Parameters for Solver Source: https://gorgonia.org/tutorials/iris Defines the model parameters (theta) that the solver will update. The solver operates on ValueGrad interfaces, and *Node fulfills this. ```go model := []gorgonia.ValueGrad{theta} ``` -------------------------------- ### Access and Set Tensor Data Source: https://gorgonia.org/tensor Illustrates how to access a specific element in a tensor using `At` and how to modify it using `SetAt`. Note that dimensions are 0-indexed. ```go b := New(WithBacking(Range(Float32, 0, 24)), WithShape(2, 3, 4)) x, _ := b.At(0, 1, 2) fmt.Printf("x: %v\n", x) b.SetAt(float32(1000), 0, 1, 2) fmt.Printf("b:\n%v", b) ``` -------------------------------- ### Fork and Clone Gorgonia CUDA Repository Source: https://gorgonia.org/cu Steps to fork the Gorgonia CUDA repository on GitHub, clone it locally, and prepare for making contributions. This involves standard Git workflow. ```bash git clone git@github.com:YOUR_USERNAME/cu.git ``` -------------------------------- ### Marshal ExprGraph to Dot Language Source: https://gorgonia.org/how-to/dot Use this Go code to create a simple graph and marshal it into the dot language format. Ensure you have the Gorgonia library imported. ```go package main import ( "fmt" "log" "gorgonia.org/gorgonia" "gorgonia.org/gorgonia/encoding/dot" ) func main() { g := gorgonia.NewGraph() var x, y *gorgonia.Node // define the expression x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x")) y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y")) gorgonia.Add(x, y) b, err := dot.Marshal(g) if err != nil { log.Fatal(err) } fmt.Println(string(b)) } ``` -------------------------------- ### Perform Automatic Differentiation with Gorgonia Source: https://gorgonia.org/how-to/autodiff Uses LispMachine to execute forward and backward mode differentiation on a scalar expression. ```go func main() { g := gorgonia.NewGraph() var x, y, z *gorgonia.Node var err error // define the expression x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x")) y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y")) z = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("z")) q, err := gorgonia.Add(x, y) if err != nil { log.Fatal(err) } result, err := gorgonia.Mul(z, q) if err != nil { log.Fatal(err) } // set initial values then run gorgonia.Let(x, -2.0) gorgonia.Let(y, 5.0) gorgonia.Let(z, -4.0) // by default, lispmachine performs forward mode and backwards mode execution m := gorgonia.NewLispMachine(g) defer m.Close() if err = m.RunAll(); err != nil { log.fatal(err) } fmt.Printf("x=%v;y=%v;z=%v\n", x.Value(), y.Value(), z.Value()) fmt.Printf("f(x,y,z)=(x+y)*z\n") fmt.Printf("f(x,y,z) = %v\n", result.Value()) if xgrad, err := x.Grad(); err == nil { fmt.Printf("df/dx: %v\n", xgrad) } if ygrad, err := y.Grad(); err == nil { fmt.Printf("df/dy: %v\n", ygrad) } if xgrad, err := z.Grad(); err == nil { fmt.Printf("df/dz: %v\n", xgrad) } } ``` ```bash $ go run main.go x=-2;y=5;z=-4 f(x,y,z)=(x+y)*z f(x,y,z) = -12 df/dx: -4 df/dy: -4 df/dz: 3 ``` -------------------------------- ### Visualize MNIST Image Source: https://gorgonia.org/tutorials/mnist Loads MNIST data, processes the first element into a grayscale image, and saves it as a PNG file. ```go import ( //... "image" "image/png" "gorgonia.org/gorgonia/examples/mnist" "gorgonia.org/tensor" "gorgonia.org/tensor/native" ) func main() { inputs, targets, err := mnist.Load("train", "./testdata", tensor.Float64) if err != nil { log.Fatal(err) } cols := inputs.Shape()[1] imageBackend := make([]uint8, cols) for i := 0; i < cols; i++ { v, _ := inputs.At(0, i) imageBackend[i] = uint8((v.(float64) - 0.1) * 0.9 * 255) } img := &image.Gray{ Pix: imageBackend, Stride: 28, Rect: image.Rect(0, 0, 28, 28), } w, _ := os.Create("output.png") vals, _ := native.MatrixF64(targets.(*tensor.Dense)) fmt.Println(vals[0]) err = png.Encode(w, img) } ``` -------------------------------- ### VM Interface Definition Source: https://gorgonia.org/reference/vm Defines the core interface for a Virtual Machine (VM) in Gorgonia, outlining the methods for computation and resource management. ```APIDOC ## VM Interface ### Description A VM in Gorgonia is an object that understands the expression graph and has implemented the ability to perform computation with it. Technically, it is an `interface{}` with three methods. ### Methods - **RunAll() error**: Executes all pending operations in the VM. - **Reset()**: Resets the VM to its initial state. - **Close() error**: Closes all machine resources (e.g., CUDA, loggers). ### Available VM Implementations - Go Machine - LispMachine - Tapemachine These VMs function differently and may take different inputs. ``` -------------------------------- ### Perform Symbolic Differentiation with Gorgonia Source: https://gorgonia.org/how-to/autodiff Uses TapeMachine to compute gradients symbolically for a defined graph expression. ```go func main() { g := gorgonia.NewGraph() var x, y, z *gorgonia.Node var err error // define the expression x = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("x")) y = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("y")) z = gorgonia.NewScalar(g, gorgonia.Float64, gorgonia.WithName("z")) q, err := gorgonia.Add(x, y) if err != nil { log.Fatal(err) } result, err := gorgonia.Mul(z, q) if err != nil { log.Fatal(err) } if grads, err = Grad(result,z, x, y); err != nil { log.Fatal(err) } // set initial values then run gorgonia.Let(x, -2.0) gorgonia.Let(y, 5.0) gorgonia.Let(z, -4.0) machine := gorgonia.NewTapeMachine(g) defer machine.Close() if err = machine.RunAll(); err != nil { log.Fatal(err) } fmt.Printf("x=%v;y=%v;z=%v\n", x.Value(), y.Value(), z.Value()) fmt.Printf("f(x,y,z)=(x+y)*z\n") fmt.Printf("f(x,y,z) = %v\n", result.Value()) if zgrad, err := z.Grad(); err == nil { fmt.Printf("dz/dx: %v | %v\n", zgrad, grads[0].Value()) } if xgrad, err := x.Grad(); err == nil { fmt.Printf("dz/dx: %v | %v\n", xgrad, grads[1].Value()) } if ygrad, err := y.Grad(); err == nil { fmt.Printf("dz/dy: %v | %v\n", ygrad, grads[2].Value()) } } ``` ```bash $ go run main.go x=-2;y=5;z=-4 f(x,y,z)=(x+y)*z f(x,y,z) = -12 df/dx: -4 | -4 df/dy: -4 | -4 df/dz: 3 | 3 ``` -------------------------------- ### Perform Backpropagation Source: https://gorgonia.org/tutorials/mnist Executes symbolic backpropagation and defines the learnable nodes. ```go gorgonia.Grad(cost, m.learnables()...) ``` ```go func (m *convnet) learnables() gorgonia.Nodes { return gorgonia.Nodes{m.w0, m.w1, m.w2, m.w3, m.w4} } ``` -------------------------------- ### Log Training Progress Source: https://gorgonia.org/tutorials/iris Prints the current value of theta, iteration count, cost, and accuracy during training. This helps monitor the learning process. ```go fmt.Printf("theta: %2.2f Iter: %v Cost: %2.3f Accuracy: %2.2f \r", theta.Value(), i, cost.Value(), accuracy(predicted.Data().([]float64), y.Value().Data().([]float64))) ``` -------------------------------- ### Assign values to input nodes Source: https://gorgonia.org/tutorials/hello-world Uses the `Let` function to assign concrete values (2.0 for x, 2.5 for y) to the previously defined input nodes. ```Go gorgonia.Let(x, 2.0) gorgonia.Let(y, 2.5) ``` -------------------------------- ### Create a new Hugo content page Source: https://gorgonia.org/getting-started/contributing-doc Use this Hugo command to create a new Markdown file for documentation content. Ensure you specify the correct directory based on the content type. ```bash hugo new content/about/mypage.md ``` -------------------------------- ### PubSub Run Method Signature Source: https://gorgonia.org/reference/vm/gomachine Signature for the `run` method of the `pubsub` struct, which initiates the broadcast and merge operations for all registered publishers and subscribers. ```go func (p *pubsub) run(ctx context.Context) (context.CancelFunc, *sync.WaitGroup) { ... } ``` -------------------------------- ### Run automatic differentiation with LispMachine Source: https://gorgonia.org/how-to/autodiff Execute the graph using the LispMachine to automatically compute gradients. ```go m := gorgonia.NewLispMachine(g) defer m.Close() if err = m.RunAll(); err != nil { log.fatal(err) } ``` -------------------------------- ### Visualize Dataset with Gonum Plotter Source: https://gorgonia.org/tutorials/iris Generates a PNG image visualizing dataset points, plotting sepal length against sepal width, categorized by species. Requires `gonum.org/v1/plot` libraries. The output is returned as a byte slice and also saved to 'out.png'. ```go import ( "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/plotutil" "gonum.org/v1/plot/vg" "gonum.org/v1/plot/vg/draw" ) func plotData(x []float64, a []float64) []byte { p, err := plot.New() if err != nil { log.Fatal(err) } p.Title.Text = "sepal length & width" p.X.Label.Text = "length" p.Y.Label.Text = "width" p.Add(plotter.NewGrid()) l := len(x) / len(a) for k := 1; k <= 3; k++ { data0 := make(plotter.XYs, 0) for i := 0; i < len(a); i++ { if k != int(a[i]) { continue } x1 := x[i*l+0] // sepal_length y1 := x[i*l+1] // sepal_width data0 = append(data0, plotter.XY{X: x1, Y: y1}) } data, err := plotter.NewScatter(data0) if err != nil { log.Fatal(err) } data.GlyphStyle.Color = plotutil.Color(k - 1) data.Shape = &draw.PyramidGlyph{} p.Add(data) p.Legend.Add(fmt.Sprint(k), data) } w, err := p.WriterTo(4*vg.Inch, 4*vg.Inch, "png") if err != nil { panic(err) } var b bytes.Buffer writer := bufio.NewWriter(&b) w.WriteTo(writer) ioutil.WriteFile("out.png", b.Bytes(), 0644) return b.Bytes() } ``` -------------------------------- ### Benchmark Comparison: CUDA vs. Non-CUDA Source: https://gorgonia.org/reference/cuda This benchmark demonstrates the performance difference when using CUDA for operations like 'sigmoid' compared to standard Go implementations. Note that the CUDA kernel used is a basic implementation. ```go BenchmarkOneMilCUDA-8 300 3348711 ns/op BenchmarkOneMil-8 50 33169036 ns/op ``` -------------------------------- ### Create Gorgonia Model for Prediction Source: https://gorgonia.org/tutorials/iris Constructs the computational graph (exprgraph) for predictions using loaded weights and input nodes. This code assumes weights have been loaded. ```go g := gorgonia.NewGraph() theta := gorgonia.NodeFromAny(g, thetaT, gorgonia.WithName("theta")) values := make([]float64, 5) xT := tensor.New(tensor.WithBacking(values)) x := gorgonia.NodeFromAny(g, xT, gorgonia.WithName("x")) y, err := gorgonia.Mul(x, theta) ``` -------------------------------- ### Define Tensor Preparation Functions Source: https://gorgonia.org/tutorials/mnist Functions for converting raw MNIST data into Gorgonia tensors. ```go func prepareX(M []RawImage, dt tensor.Dtype) (retVal tensor.Tensor) func prepareY(N []Label, dt tensor.Dtype) (retVal tensor.Tensor) ``` -------------------------------- ### Verify CUDA device with cudatest Source: https://gorgonia.org/how-to/troubleshoot-gpu-issues Executes `cudatest` with a specified GPU to verify CUDA initialization and retrieve device information. This confirms that the selected GPU is recognized and functional by CUDA. ```bash $ CUDA_VISIBLE_DEVICES=0 cudatest CUDA version: 11000 CUDA devices: 1 Device 0 ======== Name : "Tesla K20Xm" Clock Rate: 732000 kHz Memory : 5977800704 bytes Compute : 3.5 ``` -------------------------------- ### Execute state machine Source: https://gorgonia.org/reference/vm/gomachine Method to run the node state machine until completion. ```go func (n *node) Compute(ctx context.Context) error { for state := defaultState; state != nil; { state = state(ctx, n) } return n.err } ``` -------------------------------- ### PubSub Structure Definition Source: https://gorgonia.org/reference/vm/gomachine Defines the `pubsub` struct, which aggregates publishers and subscribers and is responsible for setting up the channel network for communication. ```go type pubsub struct { publishers []*publisher subscribers []*subscriber } ``` -------------------------------- ### Identify GPUs with nvidia-smi Source: https://gorgonia.org/how-to/troubleshoot-gpu-issues Use `nvidia-smi` to list all detected GPUs and their CUDA compatibility. This helps in identifying which GPUs can be used with CUDA. ```bash Thu Jul 16 17:41:10 2020 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 450.51.05 Driver Version: 450.51.05 CUDA Version: 11.0 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla K20Xm On | 00000000:06:00.0 Off | 0 | | N/A 33C P8 16W / 235W | 0MiB / 5700MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 GeForce GT 1030 On | 00000000:07:00.0 On | N/A | | 35% 33C P0 N/A / 30W | 656MiB / 1994MiB | 51% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | 1 N/A N/A XXXX G /usr/lib/xorg/Xorg 270MiB | | 1 N/A N/A XXXX G /usr/bin/PROGRAMNAME 77MiB | | 1 N/A N/A XXXX G /usr/bin/PROGRAMNAME 68MiB | | 1 N/A N/A XXXX G ...AAAAAAAAA= --shared-files 221MiB | +-----------------------------------------------------------------------------+ ``` -------------------------------- ### Monitor CUDA Usage with nvidia-smi Source: https://gorgonia.org/tutorials/mnist-cuda Run this command in a separate window to monitor GPU utilization and memory usage while the CUDA application is running. It displays driver and CUDA versions. ```bash ~ nvidia-smi Sun Feb 16 22:05:15 2020 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------| | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 Tesla M60 On | 00000000:00:1E.0 Off | 0 | | N/A 54C P0 73W / 150W | 841MiB / 7618MiB | 76% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | 0 18614 C /tmp/go-build629284435/b001/exe/main 372MiB | +-----------------------------------------------------------------------------+ ``` -------------------------------- ### Create a (2,3,4) 3-Tensor Source: https://gorgonia.org/tensor Shows how to create a 3-dimensional tensor with float32 data. The `Range` function is used to populate the backing data. ```go b := New(WithBacking(Range(Float32, 0, 24)), WithShape(2, 3, 4)) fmt.Printf("b:\n%1.1f\n", b) ``` -------------------------------- ### List AWS Deep Learning AMIs Source: https://gorgonia.org/tutorials/mnist-cuda Use this AWS CLI command to find AMIs with the CUDA toolkit pre-installed. These are tested on g3s.xlarge instances. ```bash ~ aws ec2 describe-images --owners amazon --filters 'Name=state,Values=available' 'Name=name,Values=Deep Learning AMI (Ubuntu)*' --query 'sort_by(Images, &CreationDate)[].Name' ``` -------------------------------- ### Define state machine actions Source: https://gorgonia.org/reference/vm/gomachine Required state functions for node operations. ```go func defaultState(context.Context, *node) stateFn { ... } func receiveInput(context.Context, *node) stateFn { ... } func computeFwd(context.Context, *node) stateFn { ... } func emitOutput(context.Context, *node) stateFn { ... } ``` -------------------------------- ### Implement Matrix Interface Wrapper Source: https://gorgonia.org/how-to/dataframe Defines a wrapper struct to allow a gota DataFrame to satisfy the gonum Matrix interface. ```go type matrix struct { dataframe.DataFrame } func (m matrix) At(i, j int) float64 { return m.Elem(i, j).Float() } func (m matrix) T() mat.Matrix { return mat.Transpose{Matrix: m} } ```