@@ -16,16 +16,18 @@ use linfa_linear::FittedLinearRegression;
1616use ndarray:: { Array , Array2 , ArrayBase , FixedInitializer , Ix1 , Ix2 , OwnedRepr } ;
1717use rand:: rngs:: StdRng ;
1818use rand:: { RngCore , SeedableRng } ;
19+ use regex:: Regex ;
1920use serde:: { Deserialize , Serialize } ;
2021use std:: collections:: BTreeMap ;
2122use std:: convert:: Infallible ;
2223use std:: error:: Error ;
2324use std:: fs:: File ;
2425use std:: hint:: black_box;
2526use std:: io:: { BufRead , BufReader } ;
26- use std:: iter;
2727use std:: ops:: Div ;
28+ use std:: str:: FromStr ;
2829use std:: time:: { Duration , Instant } ;
30+ use std:: { fs, iter} ;
2931
3032#[ derive( Serialize , Deserialize , Copy , Clone ) ]
3133#[ serde( tag = "kind" ) ]
@@ -74,6 +76,16 @@ struct OperationModel {
7476 mutate : FittedLinearRegression < f64 > ,
7577}
7678
79+ type DataRepr = DatasetBase < ArrayBase < OwnedRepr < f64 > , Ix2 > , ArrayBase < OwnedRepr < f64 > , Ix1 > > ;
80+
81+ struct OperationData {
82+ crossover : DataRepr ,
83+ evaluate : DataRepr ,
84+ fix : DataRepr ,
85+ generate : DataRepr ,
86+ mutate : DataRepr ,
87+ }
88+
7789const SUBJECTS : & ' static [ & ' static str ] = & [ "csv" , "rest" , "scriptsizec" , "xml" ] ;
7890
7991#[ derive( Default ) ]
@@ -104,13 +116,12 @@ where
104116 }
105117}
106118
119+ type ModelWithDataset = ( FittedLinearRegression < f64 > , DataRepr ) ;
120+
107121fn regress < const DIM : usize > (
108122 measurements : Vec < ( f64 , [ f64 ; DIM ] ) > ,
109123 features : [ & ' static str ; DIM ] ,
110- ) -> (
111- FittedLinearRegression < f64 > ,
112- DatasetBase < ArrayBase < OwnedRepr < f64 > , Ix2 > , ArrayBase < OwnedRepr < f64 > , Ix1 > > ,
113- )
124+ ) -> ModelWithDataset
114125where
115126 [ f64 ; DIM ] : FixedInitializer < Elem = f64 > , // give the compiler a little help
116127{
@@ -217,7 +228,7 @@ where
217228 println ! ( "RS models for {subject}:" ) ;
218229
219230 // generation
220- let mut samples = Vec :: with_capacity ( DISTR_SEGMENTS ) ;
231+ let mut samples = Vec :: new ( ) ;
221232 for & ( size, seed) in & distributed {
222233 let ( time, generated) = measure ( StdRng :: seed_from_u64 ( seed) , |sampler| {
223234 B :: generate ( sampler, & mut generator)
@@ -246,7 +257,7 @@ where
246257 ) ;
247258
248259 // fixing
249- let mut samples = Vec :: with_capacity ( DISTR_SEGMENTS ) ;
260+ let mut samples = Vec :: new ( ) ;
250261 for & ( size, seed) in & distributed {
251262 let generated = B :: generate ( & mut StdRng :: seed_from_u64 ( seed) , & mut generator) ;
252263 let mut local_sampler = StdSampler :: seed_from_u64 ( 0xdeadbeef ) ;
@@ -269,7 +280,7 @@ where
269280 ) ;
270281
271282 // evaluate
272- let mut samples = Vec :: with_capacity ( DISTR_SEGMENTS ) ;
283+ let mut samples = Vec :: new ( ) ;
273284 for & ( size, seed) in & distributed {
274285 let generated = B :: generate ( & mut StdRng :: seed_from_u64 ( seed) , & mut generator) ;
275286 let ( time, _) = measure ( generated, |fixed| {
@@ -290,7 +301,7 @@ where
290301 ) ;
291302
292303 // mutation
293- let mut samples = Vec :: with_capacity ( DISTR_SEGMENTS ) ;
304+ let mut samples = Vec :: new ( ) ;
294305 for & ( size, seed) in & distributed {
295306 let generated = B :: generate ( & mut StdRng :: seed_from_u64 ( seed) , & mut generator) ;
296307 let count = generated. count_nodes ( ) ;
@@ -341,7 +352,7 @@ where
341352 ) ;
342353
343354 // crossover
344- let mut samples = Vec :: with_capacity ( DISTR_SEGMENTS ) ;
355+ let mut samples = Vec :: new ( ) ;
345356 for & ( size1, seed1) in distributed
346357 . chunks ( distributed. len ( ) / CROSSOVERS )
347358 . map ( |a| a. first ( ) . unwrap ( ) )
@@ -465,8 +476,20 @@ where
465476}
466477
467478fn main ( ) -> Result < ( ) , Box < dyn Error > > {
479+ // regexes for extracting execution data later
480+ let time_re = Regex :: new ( r"^user\t([0-9]+)m([0-9]+\.[0-9]+)s$" ) . unwrap ( ) ;
481+ // reported isla multipliers
482+ let mut isla = HashMap :: new ( ) ;
483+ isla. extend ( [
484+ ( "csv" , 1335.0 ) ,
485+ ( "rest" , 146.0 ) ,
486+ ( "scriptsizec" , 29.0 ) ,
487+ ( "xml" , 183.0 ) ,
488+ ] ) ;
489+
468490 let mut fandango_models = HashMap :: new ( ) ;
469- for subject in SUBJECTS {
491+ let mut fandango_data = HashMap :: new ( ) ;
492+ for & subject in SUBJECTS {
470493 let mut crossovers = Vec :: new ( ) ;
471494 let mut evaluates = Vec :: new ( ) ;
472495 let mut fixes = Vec :: new ( ) ;
@@ -525,64 +548,65 @@ fn main() -> Result<(), Box<dyn Error>> {
525548 }
526549
527550 println ! ( "Fandango models for {subject}:" ) ;
528- let ( generate, data ) = regress ( generates, [ "size" ] ) ;
551+ let ( generate, generate_data ) = regress ( generates, [ "size" ] ) ;
529552 println ! (
530553 " generate: {:.2} microseconds/node (MAE = {:.2}, {} samples)" ,
531554 generate. params( ) [ 0 ] * 1_000_000f64 ,
532- ( generate. predict( & data . records) - data . targets)
555+ ( generate. predict( & generate_data . records) - generate_data . targets. view ( ) )
533556 . mapv( |f| f. abs( ) )
534557 . mean( )
535558 . unwrap_or( 0.0 )
536559 * 1_000_000f64 ,
537- data . records. len( ) ,
560+ generate_data . records. len( ) ,
538561 ) ;
539- let ( fix, data ) = regress ( fixes, [ "size" ] ) ;
562+ let ( fix, fix_data ) = regress ( fixes, [ "size" ] ) ;
540563 println ! (
541564 " fix: {:.2} microseconds/node (MAE = {:.2}, {} samples)" ,
542565 fix. params( ) [ 0 ] * 1_000_000f64 ,
543- ( fix. predict( & data . records) - data . targets)
566+ ( fix. predict( & fix_data . records) - fix_data . targets. view ( ) )
544567 . mapv( |f| f. abs( ) )
545568 . mean( )
546569 . unwrap_or( 0.0 )
547570 * 1_000_000f64 ,
548- data . records. len( ) ,
571+ fix_data . records. len( ) ,
549572 ) ;
550- let ( evaluate, data ) = regress ( evaluates, [ "size" ] ) ;
573+ let ( evaluate, evaluate_data ) = regress ( evaluates, [ "size" ] ) ;
551574 println ! (
552575 " evaluate: {:.2} microseconds/node (MAE = {:.2}, {} samples)" ,
553576 evaluate. params( ) [ 0 ] * 1_000_000f64 ,
554- ( evaluate. predict( & data . records) - data . targets)
577+ ( evaluate. predict( & evaluate_data . records) - evaluate_data . targets. view ( ) )
555578 . mapv( |f| f. abs( ) )
556579 . mean( )
557580 . unwrap_or( 0.0 )
558581 * 1_000_000f64 ,
559- data . records. len( ) ,
582+ evaluate_data . records. len( ) ,
560583 ) ;
561- let ( mutate, data ) = regress ( mutates, [ "size" , "mutated" ] ) ;
584+ let ( mutate, mutate_data ) = regress ( mutates, [ "size" , "mutated" ] ) ;
562585 println ! (
563586 " mutate: {:.2} microseconds/node + {:.2} microseconds/node generated (MAE = {:.2}, {} samples)" ,
564587 mutate. params( ) [ 0 ] * 1_000_000f64 ,
565588 mutate. params( ) [ 1 ] * 1_000_000f64 ,
566- ( mutate. predict( & data . records) - data . targets)
589+ ( mutate. predict( & mutate_data . records) - mutate_data . targets. view ( ) )
567590 . mapv( |f| f. abs( ) )
568591 . mean( )
569592 . unwrap_or( 0.0 )
570593 * 1_000_000f64 ,
571- data . records. len( ) ,
594+ mutate_data . records. len( ) ,
572595 ) ;
573- let ( crossover, data) = regress ( crossovers, [ "parent1" , "parent2" , "child1" , "child2" ] ) ;
596+ let ( crossover, crossover_data) =
597+ regress ( crossovers, [ "parent1" , "parent2" , "child1" , "child2" ] ) ;
574598 println ! (
575599 " crossover: {:.2} microseconds/node of parent 1 + {:.2} microseconds/node of parent 2 + {:.2} microseconds/node of child 1 + {:.2} microseconds/node of child 2 (MAE = {:.2}, {} samples)" ,
576600 crossover. params( ) [ 0 ] * 1_000_000f64 ,
577601 crossover. params( ) [ 1 ] * 1_000_000f64 ,
578602 crossover. params( ) [ 2 ] * 1_000_000f64 ,
579603 crossover. params( ) [ 3 ] * 1_000_000f64 ,
580- ( crossover. predict( & data . records) - data . targets)
604+ ( crossover. predict( & crossover_data . records) - crossover_data . targets. view ( ) )
581605 . mapv( |f| f. abs( ) )
582606 . mean( )
583607 . unwrap_or( 0.0 )
584608 * 1_000_000f64 ,
585- data . records. len( ) ,
609+ crossover_data . records. len( ) ,
586610 ) ;
587611 fandango_models. insert (
588612 subject,
@@ -594,6 +618,16 @@ fn main() -> Result<(), Box<dyn Error>> {
594618 mutate,
595619 } ,
596620 ) ;
621+ fandango_data. insert (
622+ subject,
623+ OperationData {
624+ crossover : crossover_data,
625+ evaluate : evaluate_data,
626+ fix : fix_data,
627+ generate : generate_data,
628+ mutate : mutate_data,
629+ } ,
630+ ) ;
597631 }
598632
599633 let mut rs_models = HashMap :: new ( ) ;
@@ -605,5 +639,44 @@ fn main() -> Result<(), Box<dyn Error>> {
605639 ) ;
606640 rs_models. insert ( "xml" , perform_benchmark :: < xml:: Benchmark > ( "xml" ) ) ;
607641
642+ for subject in [ "csv" , "rest" , "scriptsizec" , "xml" ] {
643+ let mut time_elapsed = 0f64 ;
644+ for trial in 1 ..=5 {
645+ let experiment_output = fs:: read_to_string ( format ! (
646+ "baselines/profiling-results/{subject}/{trial}/experiment_output.txt"
647+ ) ) ?;
648+
649+ let time_captures = time_re. captures ( & experiment_output) . unwrap ( ) ;
650+ time_elapsed += ( usize:: from_str ( time_captures. get ( 1 ) . unwrap ( ) . as_str ( ) ) . unwrap ( ) * 60 )
651+ as f64
652+ + f64:: from_str ( time_captures. get ( 2 ) . unwrap ( ) . as_str ( ) ) . unwrap ( ) ;
653+ }
654+
655+ let original_time = time_elapsed;
656+ let data = fandango_data. get ( subject) . unwrap ( ) ;
657+ let modeled = rs_models. get ( subject) . unwrap ( ) ;
658+
659+ let mut apply_model = |data : & DataRepr , model : & FittedLinearRegression < f64 > | {
660+ let original_expended = data. targets . sum ( ) ;
661+ let predicted_expended = model. predict ( & data. records ) . sum ( ) ;
662+ time_elapsed = time_elapsed + predicted_expended - original_expended;
663+ } ;
664+
665+ apply_model ( & data. generate , & modeled. generate ) ;
666+ apply_model ( & data. fix , & modeled. fix ) ;
667+ apply_model ( & data. evaluate , & modeled. evaluate ) ;
668+ apply_model ( & data. mutate , & modeled. mutate ) ;
669+ apply_model ( & data. crossover , & modeled. crossover ) ;
670+
671+ let duration_multiplier = ( 60 * 60 ) as f64 / original_time; // scale to one hour
672+ let scaled_time = time_elapsed * duration_multiplier;
673+ let computed_isla = ( 60 * 60 ) as f64 * * isla. get ( subject) . unwrap ( ) ;
674+
675+ println ! (
676+ "{scaled_time} seconds => 1 hour => {} days" ,
677+ computed_isla / ( 60 * 60 * 24 ) as f64
678+ ) ;
679+ }
680+
608681 Ok ( ( ) )
609682}
0 commit comments