Files
wickra/examples/go/parallel_assets/main.go
T

81 lines
1.7 KiB
Go
Raw Normal View History

// Run SMA(20) batch over a panel of assets, serial vs goroutine fan-out, and
// report the speedup.
package main
import (
"fmt"
"os"
"runtime"
"strconv"
"sync"
"time"
wickra "github.com/wickra-lib/wickra/bindings/go"
"github.com/wickra-lib/wickra/examples/go/internal/market"
)
func main() {
assets := argInt(1, 500)
bars := argInt(2, 20_000)
panel := make([][]float64, assets)
for a := 0; a < assets; a++ {
panel[a] = market.SyntheticPricesFrom(bars, 50.0+float64(a)*0.1)
}
// Warm up so the comparison is fair.
if warm, err := wickra.NewSma(20); err == nil {
warm.Batch(panel[0])
warm.Close()
}
sink := 0.0
start := time.Now()
for a := 0; a < assets; a++ {
sma, _ := wickra.NewSma(20)
result := sma.Batch(panel[a])
sma.Close()
sink += result[len(result)-1]
}
serial := time.Since(start)
lasts := make([]float64, assets)
start = time.Now()
var wg sync.WaitGroup
work := make(chan int, assets)
for w := 0; w < runtime.GOMAXPROCS(0); w++ {
wg.Add(1)
go func() {
defer wg.Done()
for a := range work {
sma, _ := wickra.NewSma(20)
result := sma.Batch(panel[a])
sma.Close()
lasts[a] = result[len(result)-1]
}
}()
}
for a := 0; a < assets; a++ {
work <- a
}
close(work)
wg.Wait()
parallel := time.Since(start)
serialMs := float64(serial.Microseconds()) / 1000.0
parallelMs := float64(parallel.Microseconds()) / 1000.0
fmt.Printf("%d assets x %d bars, SMA(20) batch:\n", assets, bars)
fmt.Printf(" serial %8.1f ms\n", serialMs)
fmt.Printf(" parallel %8.1f ms (%.1fx speedup)\n", parallelMs, serialMs/max(parallelMs, 1e-9))
_ = sink
}
func argInt(i, def int) int {
if len(os.Args) > i {
if v, err := strconv.Atoi(os.Args[i]); err == nil {
return v
}
}
return def
}