int main(int argc, char *argv[]){ /* Itteration Variables */ int i = 1; int gen = 0; double bestSSE = DBL_MAX; /* Creating performance variables */ double genDiv = 0; double genSSE[3] = {0,0,0}; /* worst, avg, best */ double sseError[MAXPOP]; double val[NUMPOINTS][2]; /* Genetic Paramenters */ int populationSize = 500; /* Population size (constant) */ int treeDepth = 15; /* Maximum Tree Depth */ int maxGenerations = 50; /* Maximum Number of generations */ double sseGoal = 0.5; /* SSE error goal (for spartan) */ double pruneFactor = 0.0; /* Probability that a branch will be prunned */ double constProb = 0.60; /* Probability that a leaf will be a randomly choose (0,1) constant */ double mutationRate = 0.20; /* Mutation Rate (probability that a node will be mutated */ double swapRate = 0.7; /* Probability that crossover will occur */ double tournamentFraction = 0.40; /* fraction of individuals selected by tournament */ double rankFraction = 0.50; /* fraction of individual selected by rank */ double spartanFraction = 0.1; /* fraction of individuals selected by rank, copied as is */ struct geneticParam genParam; /* compat representation of generation */ node *forest[MAXPOP]; /* Forest of trees */ node *bestTree; /* Output Variables */ int train = 1; int performance = 1; double evalPoint = 0; FILE *out = stdout; char bestTreeName[128]; char response[128] = "Y"; strcpy(bestTreeName,"bestTree"); /* Processing Command Line Inputs */ for (i = 1; i < argc; i++){ if (strcmp(argv[i],"--maxDepth")==0){ sscanf(argv[++i],"%d",&treeDepth); } else if (strcmp(argv[i],"--test")==0){ test(); return EXIT_SUCCESS; } else if (strcmp(argv[i],"--popSize")==0){ populationSize = atoi(argv[++i]); } else if (strcmp(argv[i],"--pruneFactor")==0){ pruneFactor = (double)atof(argv[++i]); } else if (strcmp(argv[i],"--constProb")==0){ constProb = (double)atof(argv[++i]); } else if (strcmp(argv[i],"--sseGoal")==0){ sseGoal = (double)atof(argv[++i]); } else if (strcmp(argv[i],"--mutationRate")==0){ mutationRate = (double)atof(argv[++i]); } else if (strcmp(argv[i],"--swapRate")==0){ swapRate = (double)atof(argv[++i]); } else if (strcmp(argv[i],"--tournamentFraction")==0){ tournamentFraction = (double) atof(argv[++i]); rankFraction = 1.0 - tournamentFraction; } else if (strcmp(argv[i],"--rankFraction")==0){ rankFraction = (double) atof(argv[++i]); } else if (strcmp(argv[i],"--spartanFraction")==0){ spartanFraction = (double) atof(argv[++i]); } else if (strcmp(argv[i],"--maxGen")==0){ maxGenerations = atoi(argv[++i]); } else if(strcmp(argv[i],"--bestTreeName")==0){ strcpy(bestTreeName,argv[++i]); } else if (strcmp(argv[i],"--help")==0){ usage(stdout,argv[0]); exit(EXIT_SUCCESS); } else{ fprintf(stderr,"Argument %s is not reconized\n",argv[i]); usage(stderr,argv[0]); exit(EXIT_FAILURE); } } /* Checking Input Arguments */ if (populationSize > MAXPOP){ fprintf(stderr,"population size is set to the max at %d. Change define for larger population\n",MAXPOP); populationSize = MAXPOP; } if (mutationRate > 1) mutationRate = 0.1; if (swapRate > 1) swapRate = 0.1; if (tournamentFraction + rankFraction > 1.0){ fprintf(stderr,"Tournament Fraction %5.3f and rank fraction %5.3f are greater than 1.0\n", tournamentFraction,rankFraction); fprintf(stderr,"Both are set to default values\n"); tournamentFraction = 0.9; rankFraction = 1.0 - tournamentFraction; } genParam.mutationRate = mutationRate; genParam.swapRate = swapRate; genParam.touramentFraction = tournamentFraction; genParam.rankFraction = rankFraction; genParam.spartanFraction = spartanFraction; genParam.constProb = constProb; genParam.maxDepth = treeDepth; genParam.pruneFraction = pruneFactor; splash(out); /* Train or Run? */ if (argc <= 1){ fprintf(stdout,"Preform symbolic regression with genetic programming [y/n]:\n"); fscanf(stdin,"%s",response); if (strcmp(response,"y")==0 || strcmp(response,"Y")==0) train = 1; else train = 0; fprintf(stdout,"Do you want to print the performance of the best tree [y/n]: \n"); fscanf(stdin,"%s",response); if (strcmp(response,"y")==0 || strcmp(response,"Y")==0) performance = 1; else performance = 0; } /* Run Information */ fprintf(out,"Parameters:\n"); fprintf(out,"\tPopulation Size: %d\n\tMax Tree Depth: %d\n",populationSize,treeDepth); fprintf(out,"\tPrune factor: %3.2f\n\tConstant Probability: %3.2f\n",pruneFactor,constProb); fprintf(out,"\tSSE Goal: %3.2f\n\tMax Generations: %d\n",sseGoal,maxGenerations); fprintf(out,"\tSpartan Fraction: %3.2f\n",spartanFraction); fprintf(out,"\tTournament Fraction: %3.2f\n\tRank Fraction: %5.2f\n",tournamentFraction,rankFraction); fprintf(out,"\tMutation Rate: %3.2f\n\tSwap Rate: %3.2f\n",mutationRate,swapRate); printSet(); /* Reading in the data file */ importData("proj2-data.dat",val); /* Creating the intitial population */ if (train){ srand( time(NULL)); fprintf(stdout,"Creating Intial Population\n"); rampedHalfHalf(forest,populationSize,&genParam); /* Running Generations */ fprintf(out,"Generation\tDiversity\tMean SSE\tBest SSE\n"); while(gen < maxGenerations && bestSSE > sseGoal){ /* Diversity and SSE */ genDiv = diversity(forest,populationSize); bestSSE = SSE(forest,populationSize,val,genSSE,sseError,bestTreeName); fprintf(out,"\t%d\t%3.2f\t\t%3.2e\t%3.2e\n",gen,genDiv,genSSE[1],genSSE[2]); /* Genetic Operations */ breedGeneration(forest,populationSize,sseError,&genParam); gen++; } /* Diversity and SSE */ genDiv = diversity(forest,populationSize); bestSSE = SSE(forest,populationSize,val,genSSE,sseError,bestTreeName); fprintf(out,"\t%d\t%3.2f\t\t%3.2e\t%3.2e\n",gen,genDiv,genSSE[1],genSSE[2]); /* Clean up, clean up, everybody do your share */ deleteForest(forest,populationSize); } /* Looking at the performance of the best tree */ if (performance){ sprintf(response,"%s.postfix",bestTreeName); bestTree = bestTreeSummary(out,response,val); if (argc <= 1){ fprintf(stdout,"Enter value on which to test the tree [n to escape]: \n"); while(fscanf(stdin,"%lf",&evalPoint)==1){ fprintf(stdout,"Tree(%5.3f) = %5.3f\n",evalPoint,evalTree(bestTree,evalPoint)); } deleteTree(bestTree); } } return EXIT_SUCCESS; }
void compile(boost::program_options::variables_map vm, string out_file_name, string routine_name, map<string,type*>& inputs, map<string,type*>& inouts, map<string,type*>& outputs, vector<stmt*> const& prog) { // set up signal to end search after certain amount of time int sMinutes = vm["limit"].as<int>(); if (sMinutes > 0) { int sSeconds = sMinutes * 60; signal(SIGALRM, sig_alarm_handler); alarm(sSeconds); } // search strategy enum search_strategy {exhaustive, orthogonal, random, hybrid_orthogonal, ga, debug, thread}; search_strategy strat = ga; if (vm["search"].as<std::string>().compare("ex") == 0) { strat = exhaustive; } else if (vm["search"].as<std::string>().compare("debug") == 0) { strat = debug; } else if (vm["search"].as<std::string>().compare("orthogonal") == 0) { strat = orthogonal; } else if (vm["search"].as<std::string>().compare("random") == 0) { strat = random; } else if (vm["search"].as<std::string>().compare("hybrid_orthogonal") == 0) { strat = hybrid_orthogonal; } else if (vm["search"].as<std::string>().compare("ga") == 0) { strat = ga; } else if (vm["search"].as<std::string>().compare("thread") == 0) { strat = thread; } else { std::cout << "Error: unknown search strategy (--search):" << vm["search"].as<std::string>() << "\n\n"; exit(0); } // which backend bool noptr; if (vm["backend"].as<std::string>().compare("noptr") == 0) { noptr = true; } else { noptr = false; } std::cout << noptr << std::endl; // partitiong FIXME can't turn off anymore? /* bool partitionSet = true; if (vm.count("partition_off")) { partitionSet = false; } */ bool mpi = false; if (vm.count("distributed")) { mpi = true; } string pathToTop = getcwd(NULL,0); pathToTop += "/"; // std::cout << pathToTop << std::endl; // set up temporary workspace string tmpPath, fileName, path; if (setUpWorkSpace(out_file_name, fileName, path, tmpPath, pathToTop, vm.count("delete_tmp"))) { std::cout << "Failed to set up temporary directory for unique implementations\n"; return; } // set all work to be performed in temporary work directory out_file_name = tmpPath + fileName; // {{{ COST MODELS std::list<versionData*> orderedVersions; string testParam = vm["test_param"].as<std::string>(); string start, stop, step; string::size_type pos = testParam.find_first_of(":"); if (pos != string::npos) start = testParam.substr(0, pos); string::size_type last = pos+1; pos = testParam.find_first_of(":",last); if (pos != string::npos) stop = testParam.substr(last, pos-last); step = testParam.substr(pos+1,string::npos); if (boost::lexical_cast<int>(start) > boost::lexical_cast<int>(stop)) { std::cout << "Test parameters are illegal (start > stop)\n"; std::cout << "\tstart: " << start << "\n"; std::cout << "\tstop: " << stop << "\n"; return; } modelMsg msg(boost::lexical_cast<int>(start), boost::lexical_cast<int>(stop), boost::lexical_cast<int>(step)); msg.pathToTop = pathToTop; // build_machine 0 -> parallel, 1 -> serial // msg.parallelArch = build_machine((char*)(pathToTop.c_str()),0); if (msg.parallelArch == NULL) { std:: cout << "Error attempting to get cost with parallel analytic model\n"; //return; } // msg.serialArch = build_machine((char*)(pathToTop.c_str()),1); // if (msg.serialArch == NULL) { // std:: cout << "Error attempting to get cost with parallel analytic model\n"; //return; // } // analyticSerial, tempCount, analyticParallel, symbolic, noModel vector<model_typ> models; models.clear(); // the model we want to rank with should go first in this list //models.push_back(noModel); models.push_back(analyticParallel); //models.push_back(analyticSerial); //models.push_back(tempCount); // }}} precision_type = vm["precision"].as<std::string>(); #ifdef MODEL_TIME // time spent in memmodel routines boost::timer memmodelTimer; double memmodelTotal = 0.0; #endif /* Model deprecated double threshold; if (vm.count("use_model")) { std::cout << "\nAnalytic model enabled\n"; threshold = vm["threshold"].as<double>(); } */ std::vector<std::pair<int, double> >::iterator itr; graph g; std::vector<algo> algos; //std::cerr << "finished parsing" << std::endl; program2graph(prog, inputs, inouts, outputs, g); //std::cerr << "graph created" << std::endl; //std::ofstream out44("lower0.dot"); //print_graph(out44, g); //out44.close(); //use yices to compute types externally //#define TYPES #ifdef TYPES std::ofstream out("lower0.dot"); print_graph(out, g); out.close(); generate_constraints(g); #endif compute_types(g); #ifdef TYPES std::ofstream out("lower1.dot"); print_graph(out, g); out.close(); exit(0); #endif update_sizes(g); update_dim_info(g); init_algos(algos); assign_algorithms(algos, g); //std::cerr << "algorithms assigned" << std::endl; assign_work(algos, g); //std::cerr << "work assigned" << std::endl; rewrite_fun rewriters[] = { flip_transpose, //0 flip_transpose_stride, //1 merge_tmp_output, //2 merge_tmp_cast_output, //3 remove_intermediate_temporary, //4 merge_gets, //5 merge_sumto_store, //6 move_temporary, //7 remove_cast_to_output, //8 remove_input_to_cast, //9 remove_cast_to_cast, //10 merge_same_cast, //11 straighten_top_level_scalar_ops,//12 reduce_reductions //13 }; optim_fun optimizers[] = { fuse_loops, //0 fuse_loops_nested, //1 merge_scalars, //2 pipeline, //3 fuse_loops_n //4 }; optim_fun_chk checkers[] = { check_fuse_loops, check_fuse_loops_nested, check_merge_scalars, check_pipeline, check_fuse_loops_n }; partition_fun partition[] = { part_mult_left_result, //0 part_mult_right_result, //1 part_mult_left_right, //2 part_mult_scl_row, //3 part_mult_scl_col, //4 partition_add_col, //5 partition_add_row, //6 part_mult_scl, //7 partition_add //8 }; rewrite_fun part_checkers[] = { check_part_mult_left_result, check_part_mult_right_result, check_part_mult_left_right, check_part_mult_scl_row, check_part_mult_scl_col, check_partition_add_col, check_partition_add_row, check_part_mult_scl, check_partition_add }; vector<rewrite_fun> rewrites(rewriters, rewriters + sizeof(rewriters) / sizeof(rewrite_fun)); vector<optim_fun> optimizations(optimizers, optimizers + sizeof(optimizers) / sizeof(optim_fun)); vector<optim_fun_chk> checks(checkers, checkers + sizeof(checkers) / sizeof(optim_fun_chk)); vector<rewrite_fun> part_checks(part_checkers, part_checkers + sizeof(part_checkers)/sizeof(rewrite_fun)); vector<partition_fun> partitioners(partition, partition + sizeof(partition) / sizeof(partition_fun)); //std::cerr << "about to start lowering and optimizine" << std::endl; std::stack<work_item> s; string history = ""; #ifdef DUMP_DOT_FILES std::ofstream out("lower1.dot"); print_graph(out, g); out.close(); #endif #ifdef DUMP_GRAPHS graphToQuery(g,out_file_name,0,0); #endif if (vm.count("correctness")) { createCorrectnessTest(g, routine_name, out_file_name, inputs, outputs,msg,noptr); } // keep copy of base graph around graph *baseGraph = new graph(g); // {{{ Partition Space code_generation codetype = threadtile; string spec = vm["level1"].as<std::string>(); if (!spec.empty()) { string::size_type pos = spec.find_first_of(" "); if (pos == string::npos) { std::cout << "Bad format for level1 arg:" << spec << endl; exit(0); } else { string codetype_str = spec.substr(0, pos); if (codetype_str == "thread") { codetype = threadtile; } else if (codetype_str == "cache") { codetype = cachetile; } else { std::cout << "Bad format for level1 arg:" << spec << endl; std::cout << "needs to be thread or cache" << endl; exit(0); } } int err = parse_range(&partition_bounds[0][0], &partition_bounds[0][1], &partition_bounds[0][2], spec.substr(pos+1)); if (err) { std::cout << "Couldn't parse range for level1: " << spec << endl; exit(0); } if (partition_bounds[0][0] > partition_bounds[0][1]) { std::cout << "Test parameters are illegal (start > stop)\n"; std::cout << "\tstart: " << partition_bounds[0][0] << "\n"; std::cout << "\tstop: " << partition_bounds[0][1] << "\n"; exit(0); } // Now level 2 string spec = vm["level2"].as<std::string>(); std::cout << "spec:" << spec << endl; if (!spec.empty()) { MAX_PARTS = 2; string::size_type pos = spec.find_first_of(" "); cout << "pos = " << pos << endl; if (pos == string::npos) { std::cout << "Bad format for level2 arg:" << spec << endl; exit(0); } else { string codetype_str = spec.substr(0, pos); cout << "codetype_str: '" << codetype_str << "'" << endl; if (codetype_str == "thread" && codetype==cachetile) { std::cout << "ERROR: threads inside tile loops not supported" << endl; std::cout << "consider swapping level1 and level2 args" << endl; exit(0); } else if (codetype_str == "cache" && codetype==threadtile) { codetype = bothtile; } else { std::cout << "Bad format for level2 arg:" << spec << endl; std::cout << "needs to be thread or cache" << endl; exit(0); } } int err = parse_range(&partition_bounds[1][0], &partition_bounds[1][1], &partition_bounds[1][2], spec.substr(pos+1)); if (err) { std::cout << "Couldn't parse range for level2: " << spec.substr(pos) << endl; exit(0); } if (partition_bounds[1][0] > partition_bounds[1][1]) { std::cout << "Test parameters are illegal (start > stop)\n"; std::cout << "\tstart: " << partition_bounds[1][0] << "\n"; std::cout << "\tstop: " << partition_bounds[1][1] << "\n"; exit(0); } } else { // Only 1 level specified MAX_PARTS = 1; } } else { // no idea what this will do! // Maybe we should just throw an error here? Or at least a warning? std::cout << "WARNING: No threading or cache tiling specified" << endl; std::cout << "Performing Loop fusion only, search may get confused" << endl; MAX_PARTS = 0; } // }}} // initializing the partition type forest // cout << "initializing partition forest..." << endl; vector< partitionTree_t* > partitionForest; buildForest(partitionForest, g, MAX_PARTS); // cout << "success" << endl; /* for (int i = 0; i < partitionForest.size(); ++i) { partitionTree_t *t = partitionForest[i]; if (t != NULL) { stringstream o; o << "tree" << i << ".dot"; ofstream treefile(o.str().c_str()); printTree(treefile, t); } } */ initial_lower(g, algos, rewrites); //std::cout << "finished lowering and rewriting" << std::endl; #ifdef DUMP_DOT_FILES std::ofstream out2("lower2.dot"); print_graph(out2, g); out2.close(); #endif #if 0 for (int i = 0; i < g.num_vertices(); ++i) if (g.info(i).op & OP_ANY_ARITHMATIC) cout << i << "\t"; cout << "\n"; #endif int reps = vm["empirical_reps"].as<int>(); if (vm.count("distributed")) { createMPIEmpiricalTest(g, routine_name, out_file_name, inputs, outputs, noptr, reps); } else if (!vm.count("empirical_off")) { createEmpiricalTest(g, routine_name, out_file_name, inputs, outputs, noptr, reps); } compile_details_t cDetails(routine_name,tmpPath,fileName, vm.count("correctness"), vm.count("use_model"), !vm.count("empirical_off"), noptr, mpi, codetype, &inputs, &inouts, &outputs); build_details_t bDetails(&part_checks, &partitioners, &checks, &optimizations, &algos, &rewrites, &models, &msg); // int maxT = max(0,msg.parallelArch->threads); // std::cout << "Testing with " << maxT << " threads, step = " << min(4,maxT) << std::endl; // int stride = 2; // {{{ Strategy cases switch (strat) { case exhaustive: { std::cout << "entering exhaustive search" << endl; //int numVersions = 5; int bestVersion = smart_exhaustive(g, *baseGraph, cDetails, bDetails); // One way or another we have selected a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case orthogonal: { std::cout << "entering orthogonal search" << endl; //int numVersions = 5; int bestVersion = orthogonal_search(g, *baseGraph, cDetails, bDetails); // One way or another we have selected a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case random: { std::cout << "entering random search" << endl; int seconds = vm["random_count"].as<int>(); int bestVersion = genetic_algorithm_search(g, *baseGraph, partitionForest, seconds, 1, false, cDetails, bDetails).best_version; // pop = 1 // One way or another we have selected a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case hybrid_orthogonal: { std::cout << "entering hybrid orthogonal search " << endl; int bestVersion = smart_hybrid_search(g, *baseGraph, cDetails, bDetails); // One way or another we have selected a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case debug: { std::cout << "entering debug search " << endl; int bestVersion = debug_search(g, *baseGraph, partitionForest, cDetails, bDetails); // One way or another we have selected a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case ga: { std::cout << "entering genetic algorithm search " << endl; bool gamaxfuse = true; if (vm.count("ga_nomaxfuse")) { gamaxfuse = false; } int seconds = vm["ga_timelimit"].as<int>(); int popsize = vm["ga_popsize"].as<int>(); int bestVersion = -1; if (vm.count("ga_noglobalthread")) { bestVersion = genetic_algorithm_search(g, *baseGraph, partitionForest, seconds, popsize, gamaxfuse, cDetails, bDetails).best_version; } else if (vm.count("ga_exthread")) { bestVersion = ga_exthread(g, *baseGraph, partitionForest, seconds, gamaxfuse, popsize, cDetails, bDetails); } else { // global thread bestVersion = ga_thread(g, *baseGraph, partitionForest, seconds, gamaxfuse, popsize, cDetails, bDetails); } // One way or another we have selected // a version we are calling the best // or we failed if (bestVersion < 0) { std::cout << "All versions failed to generate or compile\n"; return; } else { std::cout << "\n----------------------------------\n"; std::cout << "Best Version: " << fileName + "__" << bestVersion << ".c\n"; } // copy best version to same directory as input .m file // and report location handleBestVersion(fileName,path,tmpPath,bestVersion); break; } case thread: { int thread_search(graph &g, graph &baseGraph, vector<partitionTree_t*> part_forest, compile_details_t &cDet, build_details_t &bDet); std::cout << "entering thread search " << endl; thread_search(g, *baseGraph, partitionForest, cDetails, bDetails); break; } } // }}} deleteForest(partitionForest); }