-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
186 lines (159 loc) · 4.62 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package main
import (
"flag"
"fmt"
"github.com/mumax/3/cuda"
"github.com/mumax/3/engine"
_ "github.com/mumax/3/ext"
"github.com/mumax/3/prof"
"github.com/mumax/3/util"
"io/ioutil"
"log"
"os"
"os/exec"
"runtime"
"time"
)
var (
flag_silent = flag.Bool("s", false, "Don't generate any log info")
flag_vet = flag.Bool("vet", false, "Check input files for errors, but don't run them")
flag_od = flag.String("o", "", "Override output directory")
flag_force = flag.Bool("f", false, "Force start, clean existing output directory")
flag_port = flag.String("http", ":35367", "Port to serve web gui")
flag_cpuprof = flag.Bool("cpuprof", false, "Record gopprof CPU profile")
flag_memprof = flag.Bool("memprof", false, "Recored gopprof memory profile")
flag_blocklen = flag.Int("bl", 512, "CUDA 1D thread block length")
flag_blockX = flag.Int("bx", 32, "CUDA 2D thread block size X")
flag_blockY = flag.Int("by", 32, "CUDA 2D thread block size Y")
flag_gpu = flag.Int("gpu", 0, "specify GPU")
flag_sched = flag.String("sched", "yield", "CUDA scheduling: auto|spin|yield|sync")
//flag_pagelock = flag.Bool("pagelock", true, "enable CUDA memeory page-locking")
)
func main() {
engine.DeclFunc("interactive", Interactive, "Wait for GUI interaction")
defer func() { log.Println("walltime:", time.Since(engine.StartTime)) }()
flag.Parse()
log.SetPrefix("")
log.SetFlags(0)
if *flag_vet {
vet()
return
}
if *flag_silent {
log.SetOutput(ioutil.Discard)
}
log.Print(" ", engine.UNAME, "\n")
log.Print("(c) Arne Vansteenkiste, Dynamat LAB, Ghent University, Belgium", "\n")
log.Print(" This is free software without any warranty. See license.txt", "\n")
log.Print("\n")
if flag.NArg() != 1 {
log.Fatal("need one input file")
}
if *flag_od == "" { // -o not set
engine.SetOD(util.NoExt(flag.Arg(0))+".out", *flag_force)
}
runtime.GOMAXPROCS(runtime.NumCPU())
cuda.BlockSize = *flag_blocklen
cuda.TileX = *flag_blockX
cuda.TileY = *flag_blockY
cuda.Init(*flag_gpu, *flag_sched)
cuda.LockThread()
initProf()
defer prof.Cleanup()
// on crash: save magnetization for post-mortem inspection
//defer func() {
// err := recover()
// if err != nil {
// engine.SaveAs(&engine.M, "m_crash.dump")
// log.Panic(err)
// }
//}()
RunFileAndServe(flag.Arg(0))
keepBrowserAlive() // if open, that is
engine.Close()
}
// Runs a script file.
func RunFileAndServe(fname string) {
// first we compile the entire file into an executable tree
bytes, err := ioutil.ReadFile(fname)
util.FatalErr(err)
code, err2 := engine.World.Compile(string(bytes))
util.FatalErr(err2)
// now the parser is not used anymore so it can handle web requests
go engine.Serve(*flag_port)
// start executing the tree, possibly injecting commands from web gui
code.Eval()
}
// check all input files for errors, don't run.
func vet() {
status := 0
for _, f := range flag.Args() {
src, ioerr := ioutil.ReadFile(f)
util.FatalErr(ioerr)
engine.World.EnterScope() // avoid name collisions between separate files
_, err := engine.World.Compile(string(src))
engine.World.ExitScope()
if err != nil {
fmt.Println(f, ":", err)
status = 1
} else {
fmt.Println(f, ":", "OK")
}
}
os.Exit(status)
}
func Interactive() {
log.Println("entering interactive mode")
for {
f := <-engine.Inject
f()
}
}
// Enter interactive mode. Simulation is now exclusively controlled
// by web GUI (default: http://localhost:35367)
// TODO: rename
func RunInteractive() {
//engine.Pause()
log.Println("entering interactive mode")
for time.Since(engine.KeepAlive()) < timeout {
f := <-engine.Inject
f()
}
log.Println("interactive session idle: exiting")
}
// exit finished simulation this long after browser was closed
const timeout = 2 * time.Second
func keepBrowserAlive() {
if time.Since(engine.KeepAlive()) < timeout {
log.Println("keeping session open to browser")
go func() {
for {
engine.Inject <- nop // wake up RunInteractive so it may exit
time.Sleep(1 * time.Second)
}
}()
RunInteractive()
}
}
func nop() {}
// Try to open url in a browser. Instruct to do so if it fails.
func openbrowser(url string) {
for _, cmd := range browsers {
err := exec.Command(cmd, url).Start()
if err == nil {
log.Println("\n ====\n openend web interface in", cmd, "\n ====")
return
}
}
log.Println("\n ===== \n Please open ", url, " in a browser \n ====")
}
// list of browsers to try.
var browsers = []string{"x-www-browser", "google-chrome", "chromium-browser", "firefox", "ie", "iexplore"}
func initProf() {
if *flag_cpuprof {
prof.InitCPU(engine.OD)
}
if *flag_memprof {
prof.InitMem(engine.OD)
}
}