-
Notifications
You must be signed in to change notification settings - Fork 0
/
sim.go
229 lines (187 loc) · 6.95 KB
/
sim.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
package pces
import (
"fmt"
"os"
"errors"
"math"
"github.com/iti/cmdline"
"github.com/iti/mrnes"
"github.com/iti/evt/evtm"
"github.com/iti/rngstream"
"golang.org/x/exp/slices"
"path/filepath"
)
// cmdlineParams defines the parameters recognized
// on the command line
func cmdlineParams() *cmdline.CmdParser {
// command line parameters are all about file and directory locations.
// Even though we don't need the flags for the other pces structures we
// keep them here so that all the programs that build templates can use the same arguments file
// create an argument parser
cp := cmdline.NewCmdParser()
cp.AddFlag(cmdline.StringFlag, "exprmnt", true) // string name of experiment being run
cp.AddFlag(cmdline.StringFlag, "inputLib", true) // directory where model parameters are read from
cp.AddFlag(cmdline.StringFlag, "outputLib", true) // directory where measurements and traces are stored
cp.AddFlag(cmdline.StringFlag, "cp", true) //
cp.AddFlag(cmdline.StringFlag, "cpInit", true) //
cp.AddFlag(cmdline.StringFlag, "funcExec", true) // name of input file holding descriptions of functional timings
cp.AddFlag(cmdline.StringFlag, "devExec", true) // name of input file holding descriptions of device timings
cp.AddFlag(cmdline.StringFlag, "map", true) // file with mapping of comp pattern functions to hosts
cp.AddFlag(cmdline.StringFlag, "exp", true) // name of file used for run-time experiment parameters
cp.AddFlag(cmdline.StringFlag, "mdfy", false) // name of file used to modify exp experiment parameters
cp.AddFlag(cmdline.StringFlag, "topo", false) // name of output file used for topo templates
cp.AddFlag(cmdline.StringFlag, "trace", false) // path to output file of trace records
cp.AddFlag(cmdline.IntFlag, "rngseed", false) // RNG seed
cp.AddFlag(cmdline.FloatFlag, "stop", false) // run the simulation until this time (in seconds)
cp.AddFlag(cmdline.BoolFlag, "json", false) // input/output files in YAML, or JSON
cp.AddFlag(cmdline.StringFlag, "msr", true) // name of file where measurements will be written
cp.AddFlag(cmdline.BoolFlag, "verbose", false) // measure output is terse
cp.AddFlag(cmdline.StringFlag, "tunits", true) // units used in reporting time
cp.AddFlag(cmdline.BoolFlag, "container", false) // name of file where measurements will be written
return cp
}
var syn map[string]string = make(map[string]string)
var evtMgr *evtm.EventManager = evtm.New()
var useTrace bool
var termination float64
var traceFile string
var msrFile string
var cp *cmdline.CmdParser
var exprmnt string
var TimeUnits string
var MsrVerbose bool
var GlobalSeed int64 = 1234567
// ReadSimArgs defines the command line parameters expected, and reads them
func ReadSimArgs() (*cmdline.CmdParser, *evtm.EventManager) {
// define the command line parameters
cp = cmdlineParams()
// parse the command line
cp.Parse()
exprmnt = cp.GetVar("exprmnt").(string)
// string for the input directory
inputDir := cp.GetVar("inputLib").(string)
outputDir := cp.GetVar("outputLib").(string)
container := false
if cp.IsLoaded("container") {
container = true
}
// if container is set change inputDir and outputDir
// to be /tmp/extern/input and /tmp/extern/output
if container {
// create /tmp/extern if needed
inputDir = "/tmp/extern/input"
outputDir = "/tmp/extern/output"
if _, err := os.Stat("/tmp/extern"); os.IsNotExist(err) {
err := os.Mkdir("/tmp/extern", 0755)
if err != nil {
panic(errors.New("unable to create /tmp/extern"))
}
os.Mkdir("/tmp/extern/input", 0755)
os.Mkdir("/tmp/extern/output", 0755)
}
if _, err := os.Stat("/tmp/extern/output"); os.IsNotExist(err) {
err := os.Mkdir("/tmp/extern", 0755)
if err != nil {
panic(errors.New("unable to create /tmp/extern/output"))
}
}
}
// if there is no stop argument, termination is left at the largest possible time
termination = math.MaxFloat64
if cp.IsLoaded("stop") {
termination = cp.GetVar("stop").(float64)
}
TimeUnits = cp.GetVar("tunits").(string)
if !(TimeUnits == "sec" || TimeUnits == "musec" || TimeUnits == "msec" || TimeUnits == "nsec") {
panic("Time units parameter must be in {sec, msec, musec, nsec}")
}
MsrVerbose = cp.GetVar("verbose").(bool)
// make sure these directories exist
dirs := []string{inputDir}
valid, err := CheckDirectories(dirs)
if !valid {
panic(err)
}
// check for access to input files
fullpathmap := make(map[string]string)
inFiles := []string{"cp", "cpInit", "funcExec", "devExec", "exp", "mdfy", "topo", "map"}
optionalFiles := []string{"mdfy"}
fullpath := []string{}
errs := []error{}
for _, filename := range inFiles {
if !cp.IsLoaded(filename) {
if !slices.Contains(optionalFiles, filename) {
errs = append(errs, fmt.Errorf("command flag %s not included on the command line", filename))
}
continue
}
basefile := cp.GetVar(filename).(string)
fullfile := filepath.Join(inputDir, basefile)
fullpath = append(fullpath, fullfile)
fullpathmap[filename] = fullfile
syn[filename] = fullfile
}
err = ReportErrs(errs)
if err != nil {
panic(err)
}
// validate that these are all readable
ok, err := CheckReadableFiles(fullpath)
if !ok {
panic(err)
}
outputFiles := make([]string, 0)
if cp.IsLoaded("trace") {
useTrace = true
traceFile = cp.GetVar("trace").(string)
if !container {
traceFile = filepath.Join(outputDir, traceFile)
} else {
baseFile := filepath.Base(traceFile)
traceFile = filepath.Join("/tmp/extern/output", baseFile)
}
outputFiles = append(outputFiles, traceFile)
}
if cp.IsLoaded("msr") {
msrFile = cp.GetVar("msr").(string)
if !container {
msrFile = filepath.Join(outputDir, msrFile)
} else {
baseFile := filepath.Base(msrFile)
msrFile = filepath.Join("/tmp/extern/output", baseFile)
}
outputFiles = append(outputFiles, msrFile)
}
_, err = CheckOutputFiles(outputFiles)
if err != nil {
panic(err)
}
// if requested, set the rng seed
if cp.IsLoaded("rngseed") {
seed := cp.GetVar("rngseed").(int)
rngstream.SetRngStreamMasterSeed(uint64(seed))
GlobalSeed = int64(seed)
}
return cp, evtMgr
}
func RunExperiment(expCntrl evtm.EventHandlerFunction, expCmplt evtm.EventHandlerFunction) {
TraceMgr = mrnes.CreateTraceManager(exprmnt, useTrace)
// build the experiment. First the network stuff
// start the id counter at 1 (value passed is incremented before use)
mrnes.BuildExperimentNet(syn, true, 0, TraceMgr)
// now get the computation patterns and initialization structures
// cpd *CompPatternDict
// cpid *CPInitDict
// fel *FuncExecList
// cpmd *CompPatternMapDict
cpd, cpid, fel, cpmd := GetExperimentCPDicts(syn)
err := ContinueBuildExperimentCP(cpd, cpid, fel, cpmd, syn, mrnes.NumIDs, TraceMgr, evtMgr)
if err != nil {
panic(err)
}
// call function expControl to find start functions and run them
expCntrl(evtMgr, nil, nil)
evtMgr.Run(termination)
// call function expComplete to complete the experiment, write out measurements
expCmplt(evtMgr, &msrFile, &exprmnt)
}