コード例 #1
0
ファイル: b_debug.c プロジェクト: SethRobertson/libbk
/**
 * Discovery what the debug level is for the current function/package/group/program
 *
 * THREADS: MT-SAFE
 *
 *	@param B BAKA Thread/global state
 *	@param bdinfo Debug handle
 *	@param funname Function name we should look for
 *	@param pkgname Package name we should look for
 *	@param grp Group name we should look for
 *	@param flags Fun for the future
 *	@return <i>debug level</i> found for this particular function/package/group or the default debug level
 */
u_int32_t bk_debug_query(bk_s B, struct bk_debug *bdinfo, const char *funname, const char *pkgname, const char *grp, bk_flags flags)
{
  struct bk_debugnode *node;
  u_int32_t ret;

  if (!bdinfo)
  {
    bk_error_printf(B, BK_ERR_WARN, "%s: Invalid arguments\n", BK_FUNCNAME);
    return(0);
  }

#ifdef BK_USING_PTHREADS
  if (BK_GENERAL_FLAG_ISTHREADON(B) && pthread_rwlock_rdlock(&bdinfo->bd_rwlock) != 0)
    abort();
#endif /* BK_USING_PTHREADS */

  if (node = debug_search(bdinfo->bd_leveldb, (char *)funname))
  {
    ret = node->bd_level;
    goto done;
  }

  if (node = debug_search(bdinfo->bd_leveldb, (char *)pkgname))
  {
    ret = node->bd_level;
    goto done;
  }

  if (node = debug_search(bdinfo->bd_leveldb, (char *)grp))
  {
    ret = node->bd_level;
    goto done;
  }

  ret = bdinfo->bd_defaultlevel;

 done:
#ifdef BK_USING_PTHREADS
  if (BK_GENERAL_FLAG_ISTHREADON(B) && pthread_rwlock_unlock(&bdinfo->bd_rwlock) != 0)
    abort();
#endif /* BK_USING_PTHREADS */

  return(ret);
}
コード例 #2
0
ファイル: b_debug.c プロジェクト: SethRobertson/libbk
/**
 * Simple debug print function (normally used through macro)
 *
 * Produced format: "MM/DD HH:MM:SS: program[pid]: function: buf"
 *
 * THREADS: THREAD-REENTRANT
 *
 *	@param B BAKA Thread/global state
 *	@param bdinfo Debug handle
 *	@param buf The string to use as debugging information
 */
void bk_debug_iprint(bk_s B, struct bk_debug *bdinfo, const char *buf)
{
  const char *funname;
  int tmp;

  if (!(funname = bk_fun_funname(B, 0, 0)))
  {
    bk_error_printf(B, BK_ERR_NOTICE, "%s: Cannot determine function name\n",
		    BK_FUNCNAME);
    funname = "?";
  }

  if (bdinfo->bd_sysloglevel != BK_ERR_NONE)
  {
    bk_general_syslog(B, bdinfo->bd_sysloglevel, 0, "%s: %s",funname, buf);
  }

  if (bdinfo->bd_fh)
  {
    char timeprefix[40];
    char fullprefix[60];
    struct timeval tv;
    struct tm tm;
    time_t tt;
    struct bk_debugnode *node;

    gettimeofday(&tv, NULL);
    tt = tv.tv_sec;
    (void) localtime_r(&tt, &tm);

    /* <WARNING>this check should really be done with assert</WARNING> */
    if ((tmp = strftime(timeprefix, sizeof(timeprefix), "%m/%d %H:%M:%S", &tm)) != 14)
    {
      bk_error_printf(B, BK_ERR_ERR, "%s: strftime returns %d != 14\n",
		      BK_FUNCNAME, tmp);
      return;
    }

    // If this function has debugging turned on, move to subsecond timestamps
    if (bdinfo && bdinfo->bd_leveldb && (node = debug_search(bdinfo->bd_leveldb, (char *)__FUNCTION__)))
      snprintf(timeprefix+strlen(timeprefix), sizeof(timeprefix)-strlen(timeprefix), ".%06ld", tv.tv_usec);

    if (BK_GENERAL_PROGRAM(B))
      snprintf(fullprefix, sizeof(fullprefix), "%s %s[%d]", timeprefix, (char *)BK_GENERAL_PROGRAM(B), (int)getpid());
    else
      strncpy(fullprefix,timeprefix,sizeof(fullprefix));
    fullprefix[sizeof(fullprefix)-1] = 0;		/* Ensure terminating NULL */


    fprintf(bdinfo->bd_fh, "%s: %s: %s",fullprefix, funname, buf);
  }

  return;
}
コード例 #3
0
void debug_search(struct searchinfo *si)
{
	if (!si)	return;

	switch (si->type) {
	case search_messageset:
		writes("MESSAGE SET: ");
		writes(si->as);
		return;
	case search_all:
		writes("ALL");
		return;
	case search_msgflag:
		writes("FLAG \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_msgkeyword:
		writes("KEYWORD \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_not:
		writes("NOT (");
		debug_search(si->a);
		writes(")");
		return;
	case search_and:
		writes("AND (");
		debug_search(si->a);
		writes(", ");
		debug_search(si->b);
		writes(")");
		return;
	case search_or:
		writes("OR (");
		debug_search(si->a);
		writes(", ");
		debug_search(si->b);
		writes(")");
		return;
	case search_header:
		writes("HEADER \"");
		writeqs(si->cs);
		writes("\" \"");
		writeqs(si->bs);
		writes("\"");
		return;
	case search_before:
		writes("BEFORE \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_body:
		writes("BODY \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_larger:
		writes("LARGER \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_on:
		writes("ON \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_sentbefore:
		writes("SENTBEFORE \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_senton:
		writes("SENTON \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_sentsince:
		writes("SENTSINCE \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_since:
		writes("SINCE \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_smaller:
		writes("SMALLER \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_text:
		writes("TEXT \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_uid:
		writes("UID \"");
		writeqs(si->as);
		writes("\"");
		return;
	case search_orderedsubj:
		writes("ORDEREDSUBJ ");
		debug_search(si->a);
		return;
	case search_references1:
		writes("REFERENCES[References/In-Reply-To]=");
		writeqs(si->as ? si->as:"");
		writes("/");
		writeqs(si->bs ? si->bs:"");
		writes(" ");
		debug_search(si->a);
		return;
	case search_references2:
		writes("REFERENCES[Date:]=");
		writeqs(si->as ? si->as:"");
		writes(" ");
		debug_search(si->a);
		return;
	case search_references3:
		writes("REFERENCES[Subject]=");
		writeqs(si->as ? si->as:"");
		writes(" ");
		debug_search(si->a);
		return;
	case search_references4:
		writes("REFERENCES[Message-ID]=");
		writeqs(si->as ? si->as:"");
		writes(" ");
		debug_search(si->a);
		return;
	case search_arrival:
		writes("ARRIVAL");
		return;
	case search_cc:
		writes("CC");
		return;
	case search_date:
		writes("DATE");
		return;
	case search_from:
		writes("FROM");
		return;
	case search_reverse:
		writes("REVERSE");
		return;
	case search_size:
		writes("SIZE");
		return;
	case search_to:
		writes("TO");
		return;
	}
}
コード例 #4
0
ファイル: b_debug.c プロジェクト: SethRobertson/libbk
/**
 * Set an individual debug level
 *
 * N.B. Calling this function externally may be temporary--a reinit will flush
 * *ALL* items including manually set items (even if it didn't the config
 * file would override the manual items).
 *
 * THREADS: THREAD-REENTRANT
 *
 *	@param B BAKA Thread/global state
 *	@param bdinfo Debug handle
 *	@param name Name of function/group/package element to set to a particular debug @a level
 *	@param level The debug level we wish returned when queried.
 *	@see bk_debug_config
 *	@return <i>-1</i> on call failure, initialization failure, allocation failure, other error
 *	@return <BR><i>0</i> on success
 */
int bk_debug_set(bk_s B, struct bk_debug *bdinfo, const char *name, u_int32_t level)
{
  struct bk_debugnode *node;

  if (!bdinfo || !name)
  {
    bk_error_printf(B, BK_ERR_ERR, "%s: Invalid arguments\n", BK_FUNCNAME);
    return(-1);
  }

  if (!bdinfo->bd_leveldb)
  {
    bk_error_printf(B, BK_ERR_NOTICE, "%s: Debugging not configured yet\n",
		    BK_FUNCNAME);
    return(-1);
  }

#ifdef BK_USING_PTHREADS
  if (BK_GENERAL_FLAG_ISTHREADON(B) && pthread_rwlock_wrlock(&bdinfo->bd_rwlock) != 0)
    abort();
#endif /* BK_USING_PTHREADS */

  if (node = debug_search(bdinfo->bd_leveldb, (char *)name))
  {
    node->bd_level = level;
    goto done;
  }

  if (!(node = malloc(sizeof(*node))))
  {
    bk_error_printf(B, BK_ERR_ERR, "%s: Could not allocate memory to set debug level: %s\n",
		    BK_FUNCNAME, strerror(errno));
    goto error;
  }

  if (!(node->bd_name = strdup(name)))
  {
    bk_error_printf(B, BK_ERR_ERR, "%s: Could not strdup debug name %s: %s\n",name,
		    BK_FUNCNAME, strerror(errno));
    goto error;
  }

  node->bd_level = level;

  if (debug_insert(bdinfo->bd_leveldb, node) != DICT_OK)
  {
    bk_error_printf(B, BK_ERR_ERR, "%s: Could not insert debug node for %s: %s\n",
		    BK_FUNCNAME, name, debug_error_reason(bdinfo->bd_leveldb, NULL));
    goto error;
  }

  /* Set the program default debug level if the current name is the default */
  if (!strcmp(BK_DEBUG_DEFAULTLEVEL, name))
    bdinfo->bd_defaultlevel = level;

 done:
#ifdef BK_USING_PTHREADS
  if (BK_GENERAL_FLAG_ISTHREADON(B) && pthread_rwlock_unlock(&bdinfo->bd_rwlock) != 0)
    abort();
#endif /* BK_USING_PTHREADS */

  return(0);

 error:
  if (node)
  {
    if (node->bd_name)
    {
      debug_delete(bdinfo->bd_leveldb, node);
      free(node->bd_name);
    }
    free(node);
  }

#ifdef BK_USING_PTHREADS
  if (BK_GENERAL_FLAG_ISTHREADON(B) && pthread_rwlock_unlock(&bdinfo->bd_rwlock) != 0)
    abort();
#endif /* BK_USING_PTHREADS */

  return(-1);
}
コード例 #5
0
ファイル: compile.cpp プロジェクト: nelsonth/btoblas
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);
}