@@ -458,8 +458,8 @@ the given study names.`)
458
458
valueKeys := make (map [string ]bool )
459
459
for i := range studies {
460
460
for _ , run := range runs [i ] {
461
- for name := range run .Values {
462
- valueKeys [name ] = true
461
+ for key := range run .Values {
462
+ valueKeys [key ] = true
463
463
}
464
464
}
465
465
}
@@ -508,6 +508,7 @@ var (
508
508
objective: {{.Objective}}{{range $_, $value := .Params.Sorted }}
509
509
{{$value.Name}}: {{$value.Param}}{{end}}
510
510
oracle: {{printf "%T" .Oracle}}
511
+ replicates: {{.Replicates}}
511
512
` ))
512
513
513
514
runFuncMap = template.FuncMap {
@@ -521,6 +522,7 @@ var (
521
522
created: {{.run.Created.Local}}
522
523
runtime: {{.run.Runtime}}
523
524
restarts: {{.run.Retries}}
525
+ replicate: {{.run.Replicate}}
524
526
values:{{range $_, $value := .run.Values.Sorted }}
525
527
{{$value.Name}}: {{$value.Value}}{{end}}{{if .verbose}}{{range $index, $metrics := .run.Metrics}}
526
528
metrics[{{$index}}]:{{range $_, $metric := $metrics.Sorted}}
@@ -658,9 +660,10 @@ column; missing values are denoted by "NA".`)
658
660
659
661
func run (db diviner.Database , args []string ) {
660
662
var (
661
- flags = flag .NewFlagSet ("run" , flag .ExitOnError )
662
- ntrials = flags .Int ("trials" , 1 , "number of trials to run in each round" )
663
- nrounds = flags .Int ("rounds" , 1 , "number of rounds to run" )
663
+ flags = flag .NewFlagSet ("run" , flag .ExitOnError )
664
+ ntrials = flags .Int ("trials" , 1 , "number of trials to run in each round" )
665
+ nrounds = flags .Int ("rounds" , 1 , "number of rounds to run" )
666
+ replicate = flags .Int ("replicate" , 0 , "replicate to re-run" )
664
667
)
665
668
flags .Usage = func () {
666
669
fmt .Fprintln (os .Stderr , `usage: diviner run [-rounds n] [-trials n] script.dv [studies]
@@ -760,7 +763,7 @@ If no studies are specified, all defined studies are run concurrently.`)
760
763
}
761
764
err = traverse .Each (len (runs ), func (i int ) (err error ) {
762
765
log .Printf ("repeating run %s" , args [i ])
763
- runs [i ], err = runner .Run (ctx , runsStudy [i ], runs [i ].Values )
766
+ runs [i ], err = runner .Run (ctx , runsStudy [i ], runs [i ].Values , * replicate )
764
767
return
765
768
})
766
769
if err != nil {
@@ -804,7 +807,9 @@ func showScript(db diviner.Database, args []string) {
804
807
Script renders a bash script to standard output containing a function
805
808
for each of the study's datasets and the study itself. The study's
806
809
parameter values can be specified via flags; unspecified parameter
807
- values are sampled randomly from valid parameter values.` )
810
+ values are sampled randomly from valid parameter values. The
811
+ study is always invoked with replicate 0.
812
+ ` )
808
813
flags .PrintDefaults ()
809
814
os .Exit (2 )
810
815
}
@@ -840,7 +845,7 @@ values are sampled randomly from valid parameter values.`)
840
845
}
841
846
var (
842
847
study = matched [0 ]
843
- values = make ( diviner.Values )
848
+ values diviner.Values
844
849
rng = rand .New (rand .NewSource (0 ))
845
850
)
846
851
flags = flag .NewFlagSet (study .Name , flag .ExitOnError )
@@ -878,7 +883,7 @@ values are sampled randomly from valid parameter values.`)
878
883
log .Fatalf ("value %s is not valid for parameter %s %s" , val , name , p )
879
884
}
880
885
}
881
- config , err := study .Run (values , * ident )
886
+ config , err := study .Run (values , 0 , * ident )
882
887
if err != nil {
883
888
log .Fatal (err )
884
889
}
@@ -895,11 +900,9 @@ func leaderboard(db diviner.Database, args []string) {
895
900
flags = flag .NewFlagSet ("leaderboard" , flag .ExitOnError )
896
901
objectiveOverride = flags .String ("objective" , "" , "objective to use instead of studies' shared objective" )
897
902
numEntries = flags .Int ("n" , 10 , "number of top trials to display" )
898
- valuesRe = flags .String ("values" , "^$ " , "comma-separated list of anchored regular expression matching parameter values to display" )
903
+ valuesRe = flags .String ("values" , ". " , "comma-separated list of anchored regular expression matching parameter values to display" )
899
904
metricsRe = flags .String ("metrics" , "^$" , `comma-separated list of anchored regular expression matching additional metrics to display.
900
905
Each regex can be prefixed with '+' or '-'. A regex with '+' (or '-'), when combined with -best, will pick the largest (or smallest) metric from each run.` )
901
- best = flags .Bool ("best" , false ,
902
- "If set, pick the best metric from each run. Otherwise, pick the last metric reported." )
903
906
)
904
907
flags .Usage = func () {
905
908
fmt .Fprintln (os .Stderr , `usage: diviner leaderboard [-objective objective] [-n N] [-values values] [-metrics metrics] studies...
@@ -954,16 +957,25 @@ specifying regular expressions for matching them via the flags
954
957
} else {
955
958
objective = parseObjective (* objectiveOverride )
956
959
}
960
+ type trial struct {
961
+ diviner.Trial
962
+ Study string
963
+ }
957
964
var (
958
- runsMu sync.Mutex
959
- runs []diviner. Run
965
+ trialsMu sync.Mutex
966
+ trials []trial
960
967
)
961
968
err := traverser .Each (len (studies ), func (i int ) error {
962
- r , err := db .ListRuns (ctx , studies [i ].Name , diviner .Success , time.Time {})
963
- runsMu .Lock ()
964
- runs = append (runs , r ... )
965
- runsMu .Unlock ()
966
- return err
969
+ t , err := diviner .Trials (ctx , db , studies [i ])
970
+ if err != nil {
971
+ return err
972
+ }
973
+ trialsMu .Lock ()
974
+ t .Range (func (_ diviner.Value , v interface {}) {
975
+ trials = append (trials , trial {v .(diviner.Trial ), studies [i ].Name })
976
+ })
977
+ trialsMu .Unlock ()
978
+ return nil
967
979
})
968
980
if err != nil {
969
981
log .Fatal (err )
@@ -974,27 +986,27 @@ specifying regular expressions for matching them via the flags
974
986
metrics = make (map [string ]bool )
975
987
)
976
988
977
- for _ , run := range runs {
978
- if _ , ok := getMetric ( run , objective , * best ) ; ! ok {
989
+ for _ , trial := range trials {
990
+ if _ , ok := trial . Metrics [ objective . Metric ] ; ! ok {
979
991
continue
980
992
}
981
- runs [n ] = run
993
+ trials [n ] = trial
982
994
n ++
983
- for _ , m := range run .Metrics {
984
- for name := range m {
985
- metrics [name ] = true
986
- }
995
+ for name := range trial .Metrics {
996
+ metrics [name ] = true
997
+
987
998
}
988
- for name := range run .Values {
999
+ for name := range trial .Values {
989
1000
values [name ] = true
990
1001
}
991
1002
}
992
- if n < len (runs ) {
993
- log .Printf ("skipping %d runs due to missing metrics" , len (runs )- n )
1003
+ if n < len (trials ) {
1004
+ log .Printf ("skipping %d trials due to missing metrics" , len (trials )- n )
1005
+ trials = trials [:n ]
994
1006
}
995
- sort .SliceStable (runs , func (i , j int ) bool {
996
- iv , _ := getMetric ( runs [i ], objective , * best )
997
- jv , _ := getMetric ( runs [j ], objective , * best )
1007
+ sort .SliceStable (trials , func (i , j int ) bool {
1008
+ iv , _ := trials [i ]. Metrics [ objective . Metric ]
1009
+ jv , _ := trials [j ]. Metrics [ objective . Metric ]
998
1010
switch objective .Direction {
999
1011
case diviner .Maximize :
1000
1012
return jv < iv
@@ -1004,8 +1016,8 @@ specifying regular expressions for matching them via the flags
1004
1016
panic (objective )
1005
1017
}
1006
1018
})
1007
- if * numEntries > 0 && len (runs ) > * numEntries {
1008
- runs = runs [:* numEntries ]
1019
+ if * numEntries > 0 && len (trials ) > * numEntries {
1020
+ trials = trials [:* numEntries ]
1009
1021
}
1010
1022
delete (metrics , objective .Metric )
1011
1023
@@ -1029,13 +1041,12 @@ specifying regular expressions for matching them via the flags
1029
1041
return metricsOrdered [i0 - i ].Metric < metricsOrdered [i1 - i ].Metric
1030
1042
})
1031
1043
}
1032
-
1033
1044
var (
1034
1045
valuesOrdered = matchAndSort (values , * valuesRe )
1035
1046
tw tabwriter.Writer
1036
1047
)
1037
1048
tw .Init (os .Stdout , 4 , 4 , 1 , ' ' , 0 )
1038
- fmt .Fprintf (& tw , "run \t %s" , objective .Metric )
1049
+ fmt .Fprintf (& tw , "study \t %s" , objective .Metric )
1039
1050
if len (metricsOrdered ) > 0 {
1040
1051
for _ , metric := range metricsOrdered {
1041
1052
fmt .Fprint (& tw , "\t " + metric .Metric )
@@ -1045,13 +1056,18 @@ specifying regular expressions for matching them via the flags
1045
1056
fmt .Fprint (& tw , "\t " + strings .Join (valuesOrdered , "\t " ))
1046
1057
}
1047
1058
fmt .Fprintln (& tw )
1048
- for _ , run := range runs {
1049
- v , _ := getMetric (run , objective , * best )
1050
- fmt .Fprintf (& tw , "%s:%d\t %.4g" , run .Study , run .Seq , v )
1059
+ for _ , trial := range trials {
1060
+ v := trial .Metrics [objective .Metric ]
1061
+ sort .Slice (trial .Runs , func (i , j int ) bool { return trial .Runs [i ].Seq < trial .Runs [j ].Seq })
1062
+ seqs := make ([]string , len (trial .Runs ))
1063
+ for i := range seqs {
1064
+ seqs [i ] = fmt .Sprint (trial .Runs [i ].Seq )
1065
+ }
1066
+ fmt .Fprintf (& tw , "%s:%s\t %.4g" , trial .Study , strings .Join (seqs , "," ), v )
1051
1067
if len (metricsOrdered ) > 0 {
1052
1068
metrics := make ([]string , len (metricsOrdered ))
1053
1069
for i , metric := range metricsOrdered {
1054
- if v , ok := getMetric ( run , metric , * best ) ; ok {
1070
+ if v , ok := trial . Metrics [ metric . Metric ] ; ok {
1055
1071
metrics [i ] = fmt .Sprintf ("%.3g" , v )
1056
1072
} else {
1057
1073
metrics [i ] = "NA"
@@ -1062,7 +1078,7 @@ specifying regular expressions for matching them via the flags
1062
1078
if len (valuesOrdered ) > 0 {
1063
1079
values := make ([]string , len (valuesOrdered ))
1064
1080
for i , name := range valuesOrdered {
1065
- if v , ok := run .Values [name ]; ok {
1081
+ if v , ok := trial .Values [name ]; ok {
1066
1082
switch v .Kind () {
1067
1083
default :
1068
1084
values [i ] = fmt .Sprint (v )
@@ -1220,27 +1236,3 @@ func splitName(name string) (study string, seq uint64) {
1220
1236
panic (parts )
1221
1237
}
1222
1238
}
1223
-
1224
- func getMetric (run diviner.Run , objective diviner.Objective , best bool ) (float64 , bool ) {
1225
- found := false
1226
- bestValue := 0.0
1227
- for i := len (run .Metrics ) - 1 ; i >= 0 ; i -- {
1228
- m , ok := run.Metrics [i ][objective.Metric ]
1229
- if ! ok {
1230
- continue
1231
- }
1232
- if ! best {
1233
- return m , ok
1234
- }
1235
- switch {
1236
- case ! found :
1237
- bestValue = m
1238
- found = true
1239
- case objective .Direction == diviner .Maximize && m > bestValue :
1240
- bestValue = m
1241
- case objective .Direction == diviner .Minimize && m < bestValue :
1242
- bestValue = m
1243
- }
1244
- }
1245
- return bestValue , found
1246
- }
0 commit comments