diff --git a/test/yulPhaser/Phaser.cpp b/test/yulPhaser/Phaser.cpp index ca45c0771..633462865 100644 --- a/test/yulPhaser/Phaser.cpp +++ b/test/yulPhaser/Phaser.cpp @@ -159,7 +159,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_of_the_right_type, FitnessMet { m_options.metric = MetricChoice::RelativeCodeSize; m_options.metricAggregator = MetricAggregatorChoice::Sum; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); + unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); BOOST_REQUIRE(metric != nullptr); auto sumMetric = dynamic_cast(metric.get()); @@ -177,7 +177,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_respect_chromosome_repetitions_option, Fitn m_options.metric = MetricChoice::CodeSize; m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.chromosomeRepetitions = 5; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); + unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); BOOST_REQUIRE(metric != nullptr); auto averageMetric = dynamic_cast(metric.get()); @@ -195,7 +195,7 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFac m_options.metric = MetricChoice::RelativeCodeSize; m_options.metricAggregator = MetricAggregatorChoice::Average; m_options.relativeMetricScale = 10; - unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}); + unique_ptr metric = FitnessMetricFactory::build(m_options, {m_programs[0]}, {nullptr}); BOOST_REQUIRE(metric != nullptr); auto averageMetric = dynamic_cast(metric.get()); @@ -210,7 +210,11 @@ BOOST_FIXTURE_TEST_CASE(build_should_set_relative_metric_scale, FitnessMetricFac BOOST_FIXTURE_TEST_CASE(build_should_create_metric_for_each_input_program, FitnessMetricFactoryFixture) { - unique_ptr metric = FitnessMetricFactory::build(m_options, m_programs); + unique_ptr metric = FitnessMetricFactory::build( + m_options, + m_programs, + vector>(m_programs.size(), nullptr) + ); BOOST_REQUIRE(metric != nullptr); auto combinedMetric = dynamic_cast(metric.get()); @@ -218,6 +222,31 @@ BOOST_FIXTURE_TEST_CASE(build_should_create_metric_for_each_input_program, Fitne BOOST_REQUIRE(combinedMetric->metrics().size() == m_programs.size()); } +BOOST_FIXTURE_TEST_CASE(build_should_pass_program_caches_to_metrics, FitnessMetricFactoryFixture) +{ + assert(m_programs.size() == 3); + vector> caches = { + make_shared(m_programs[0]), + make_shared(m_programs[1]), + make_shared(m_programs[2]), + }; + + m_options.metric = MetricChoice::RelativeCodeSize; + unique_ptr metric = FitnessMetricFactory::build(m_options, m_programs, caches); + BOOST_REQUIRE(metric != nullptr); + + auto combinedMetric = dynamic_cast(metric.get()); + BOOST_REQUIRE(combinedMetric != nullptr); + BOOST_REQUIRE(combinedMetric->metrics().size() == caches.size()); + + for (size_t i = 0; i < caches.size(); ++i) + { + auto programBasedMetric = dynamic_cast(combinedMetric->metrics()[i].get()); + BOOST_REQUIRE(programBasedMetric != nullptr); + BOOST_TEST(programBasedMetric->programCache() == caches[i].get()); + } +} + BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(PopulationFactoryTest) diff --git a/tools/yulPhaser/Phaser.cpp b/tools/yulPhaser/Phaser.cpp index 054b6e99e..218b358a0 100644 --- a/tools/yulPhaser/Phaser.cpp +++ b/tools/yulPhaser/Phaser.cpp @@ -158,9 +158,11 @@ FitnessMetricFactory::Options FitnessMetricFactory::Options::fromCommandLine(po: unique_ptr FitnessMetricFactory::build( Options const& _options, - vector _programs + vector _programs, + vector> _programCaches ) { + assert(_programCaches.size() == _programs.size()); assert(_programs.size() > 0 && "Validations should prevent this from being executed with zero files."); vector> metrics; @@ -168,10 +170,10 @@ unique_ptr FitnessMetricFactory::build( { case MetricChoice::CodeSize: { - for (Program& program: _programs) + for (size_t i = 0; i < _programs.size(); ++i) metrics.push_back(make_unique( - move(program), - nullptr, + _programCaches[i] != nullptr ? optional{} : move(_programs[i]), + move(_programCaches[i]), _options.chromosomeRepetitions )); @@ -179,10 +181,10 @@ unique_ptr FitnessMetricFactory::build( } case MetricChoice::RelativeCodeSize: { - for (Program& program: _programs) + for (size_t i = 0; i < _programs.size(); ++i) metrics.push_back(make_unique( - move(program), - nullptr, + _programCaches[i] != nullptr ? optional{} : move(_programs[i]), + move(_programCaches[i]), _options.relativeMetricScale, _options.chromosomeRepetitions )); @@ -528,6 +530,19 @@ Phaser::CommandLineDescription Phaser::buildCommandLineDescription() ; keywordDescription.add(metricsDescription); + po::options_description cacheDescription("CACHE", lineLength, minDescriptionLength); + cacheDescription.add_options() + ( + "program-cache", + po::bool_switch(), + "Enables caching of intermediate programs corresponding to chromosome prefixes.\n" + "This speeds up fitness evaluation by a lot but eats tons of memory if the chromosomes are long. " + "Disabled by default since there's currently no way to set an upper limit on memory usage but " + "highly recommended if your computer has enough RAM." + ) + ; + keywordDescription.add(cacheDescription); + po::positional_options_description positionalDescription; positionalDescription.add("input-files", -1); @@ -583,12 +598,15 @@ AlgorithmRunner::Options Phaser::buildAlgorithmRunnerOptions(po::variables_map c void Phaser::runAlgorithm(po::variables_map const& _arguments) { auto programOptions = ProgramFactory::Options::fromCommandLine(_arguments); + auto cacheOptions = ProgramCacheFactory::Options::fromCommandLine(_arguments); auto metricOptions = FitnessMetricFactory::Options::fromCommandLine(_arguments); auto populationOptions = PopulationFactory::Options::fromCommandLine(_arguments); auto algorithmOptions = GeneticAlgorithmFactory::Options::fromCommandLine(_arguments); vector programs = ProgramFactory::build(programOptions); - unique_ptr fitnessMetric = FitnessMetricFactory::build(metricOptions, move(programs)); + vector> programCaches = ProgramCacheFactory::build(cacheOptions, programs); + + unique_ptr fitnessMetric = FitnessMetricFactory::build(metricOptions, move(programs), programCaches); Population population = PopulationFactory::build(populationOptions, move(fitnessMetric)); unique_ptr geneticAlgorithm = GeneticAlgorithmFactory::build( @@ -596,6 +614,6 @@ void Phaser::runAlgorithm(po::variables_map const& _arguments) population.individuals().size() ); - AlgorithmRunner algorithmRunner(population, vector>(programs.size(), nullptr), buildAlgorithmRunnerOptions(_arguments), cout); + AlgorithmRunner algorithmRunner(population, move(programCaches), buildAlgorithmRunnerOptions(_arguments), cout); algorithmRunner.run(*geneticAlgorithm); } diff --git a/tools/yulPhaser/Phaser.h b/tools/yulPhaser/Phaser.h index 256d9a288..ba816044c 100644 --- a/tools/yulPhaser/Phaser.h +++ b/tools/yulPhaser/Phaser.h @@ -120,7 +120,8 @@ public: static std::unique_ptr build( Options const& _options, - std::vector _programs + std::vector _programs, + std::vector> _programCaches ); };