snapshot of svn
This commit is contained in:
302
src/AutoTuning/DKSAutoTuning.cpp
Normal file
302
src/AutoTuning/DKSAutoTuning.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
#include "DKSAutoTuning.h"
|
||||
|
||||
DKSAutoTuning::DKSAutoTuning(DKSBase *base, std::string api, std::string device, int loops) {
|
||||
|
||||
base_m = base;
|
||||
api_name_m = api;
|
||||
device_name_m = device;
|
||||
loops_m = loops;
|
||||
|
||||
evaluate_time_m = true;
|
||||
}
|
||||
|
||||
DKSAutoTuning::~DKSAutoTuning() {
|
||||
params_m.clear();
|
||||
}
|
||||
|
||||
int DKSAutoTuning::setParameterValues(States state) {
|
||||
|
||||
//if states and params don't match in size something has gone wrong
|
||||
if (state.size() != params_m.size()) {
|
||||
DEBUG_MSG("Parameters and states don't match!");
|
||||
return DKS_ERROR;
|
||||
}
|
||||
|
||||
//set the value pointed by params to value saved in state
|
||||
for (unsigned int i = 0; i < params_m.size(); i++)
|
||||
params_m[i].setValue(state[i].value);
|
||||
|
||||
return DKS_SUCCESS;
|
||||
}
|
||||
|
||||
/** TODO: might need a better timing for GPU code */
|
||||
int DKSAutoTuning::evaluateFunction(double &value) {
|
||||
|
||||
int ierr = DKS_ERROR;
|
||||
DKSTimer t;
|
||||
|
||||
t.init(function_name_m);
|
||||
|
||||
if (evaluate_time_m) {
|
||||
//run for "loop" times and return the average time.
|
||||
//syncDevice() is used to make sure that nothing is running on the device before the timer starts
|
||||
// and to make sure the function has completed on the device before the time stops
|
||||
for (int j = 0; j < loops_m; j++) {
|
||||
base_m->syncDevice();
|
||||
t.start();
|
||||
ierr = f_m();
|
||||
base_m->syncDevice();
|
||||
t.stop();
|
||||
if (ierr != DKS_SUCCESS) //exit loop if kernel execution fials
|
||||
break;
|
||||
}
|
||||
|
||||
//returns
|
||||
value = t.gettime() / loops_m;
|
||||
} else {
|
||||
value = fd_m();
|
||||
ierr = DKS_SUCCESS;
|
||||
}
|
||||
|
||||
return ierr;
|
||||
}
|
||||
|
||||
void DKSAutoTuning::clearParameters() {
|
||||
params_m.clear();
|
||||
}
|
||||
|
||||
void DKSAutoTuning::exaustiveSearch() {
|
||||
|
||||
DKSTimer t;
|
||||
t.init("exaustive search");
|
||||
t.start();
|
||||
|
||||
if (params_m.size() < 2)
|
||||
return;
|
||||
|
||||
Parameter p1 = params_m[0];
|
||||
Parameter p2 = params_m[1];
|
||||
|
||||
double time;
|
||||
double mint = 1000000.0;
|
||||
int minv1 = 0;
|
||||
int minv2 = 0;
|
||||
|
||||
//std::ofstream myfile;
|
||||
//std::string filename;
|
||||
//filename = "search_" + api_name_m + "_" + device_name_m + ".dat";
|
||||
//myfile.open(filename);
|
||||
|
||||
for (double v1 = p1.min; v1 <= p1.max; v1 += p1.step) {
|
||||
for (double v2 = p2.min; v2 <= p2.max; v2 += p2.step) {
|
||||
p1.setValue(v1);
|
||||
p2.setValue(v2);
|
||||
|
||||
int ierr = evaluateFunction(time);
|
||||
|
||||
if (ierr == DKS_SUCCESS && time < mint) {
|
||||
mint = time;
|
||||
minv1 = v1;
|
||||
minv2 = v2;
|
||||
}
|
||||
if (ierr == DKS_ERROR)
|
||||
time = 1;
|
||||
|
||||
//myfile << time << "\t";
|
||||
}
|
||||
//myfile << "\n";
|
||||
}
|
||||
//myfile.close();
|
||||
|
||||
//std::cout << "Optimal launch parameters:" << std::endl;
|
||||
//std::cout << mint << "\t" << minv1 << "\t" << minv2 << std::endl;
|
||||
p1.setValue(minv1);
|
||||
p2.setValue(minv2);
|
||||
|
||||
t.stop();
|
||||
//std::cout << "exaustive search: " << t.gettime() << std::endl;
|
||||
}
|
||||
|
||||
void DKSAutoTuning::lineSearch() {
|
||||
DKSTimer t;
|
||||
t.init("line search");
|
||||
t.start();
|
||||
|
||||
double time;
|
||||
int ierr = DKS_ERROR;
|
||||
|
||||
if (params_m.size() < 1) {
|
||||
DEBUG_MSG("Need some parameters to autotune!");
|
||||
return;
|
||||
}
|
||||
|
||||
double mint = 1000000.0;
|
||||
//loop trough parameters one parameter at a time
|
||||
for (auto param : params_m) {
|
||||
int minv = param.getValue();
|
||||
|
||||
//go trough all the values of the parameter, while keeping other parameters const
|
||||
for (double i = param.min; i <= param.max; i += param.step) {
|
||||
//adjust parameters
|
||||
param.setValue(i);
|
||||
|
||||
//run for "loop" times and get average
|
||||
ierr = evaluateFunction(time);
|
||||
|
||||
//if there was no error executing the function and time is better than previou
|
||||
//min time, save the parameter configuration
|
||||
if (ierr == DKS_SUCCESS && time < mint) {
|
||||
mint = time;
|
||||
minv = i;
|
||||
}
|
||||
|
||||
} //repeat
|
||||
|
||||
param.setValue(minv);
|
||||
}
|
||||
|
||||
//DEBUG: print out the found best parameters
|
||||
for (auto param : params_m)
|
||||
std::cout << "Parameter " << param.name << " set to " << param.getValue() << std::endl;
|
||||
|
||||
std::cout << "Best time: " << mint << std::endl;
|
||||
|
||||
t.stop();
|
||||
std::cout << "Line search time: " << t.gettime() << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void DKSAutoTuning::hillClimbing(int restart_loops) {
|
||||
|
||||
DKSTimer t;
|
||||
t.init("hill climbing");
|
||||
t.start();
|
||||
|
||||
std::cout << "hill climbing" << std::endl;
|
||||
|
||||
int ierr;
|
||||
double time_current;
|
||||
double time_next;
|
||||
DKSSearchStates search(params_m);
|
||||
|
||||
std::cout << "start " << restart_loops << std::endl;
|
||||
|
||||
for (int i = 0; i < restart_loops; i++) {
|
||||
|
||||
|
||||
//init random current state
|
||||
search.initCurrentState();
|
||||
|
||||
//evaluate current state
|
||||
setParameterValues(search.getCurrentState());
|
||||
ierr = evaluateFunction(time_current);
|
||||
|
||||
//std::cout << "Start iteration " << i+1 << std::endl;
|
||||
//search.printCurrentState(time_current);
|
||||
|
||||
if (ierr == DKS_ERROR)
|
||||
continue;
|
||||
|
||||
//statr the loop
|
||||
bool topReached = false;
|
||||
while(!topReached) {
|
||||
|
||||
search.getNeighbours();
|
||||
|
||||
//get all the neighbors of the current state
|
||||
bool neighbourFound = false;
|
||||
while (!neighbourFound && search.nextNeighbourExists()) {
|
||||
|
||||
//evaluate all the neighbors of the current state
|
||||
setParameterValues(search.getNextNeighbour());
|
||||
ierr = evaluateFunction(time_next);
|
||||
|
||||
//search.printNeighbour(time_next);
|
||||
|
||||
if (ierr == DKS_ERROR)
|
||||
std::cout << "Error evaluating function" << std::endl;
|
||||
|
||||
//move to the first option that improives the solution
|
||||
if (ierr == DKS_SUCCESS && time_next < time_current) {
|
||||
time_current = time_next;
|
||||
search.moveToNeighbour();
|
||||
neighbourFound = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if no better option is found save the state and move to step 1
|
||||
if (!neighbourFound) {
|
||||
search.saveCurrentState(time_current);
|
||||
topReached = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
search.printBest();
|
||||
|
||||
t.stop();
|
||||
std::cout << "hill climbing: " << t.gettime() << std::endl;
|
||||
}
|
||||
|
||||
void DKSAutoTuning::simulatedAnnealing(double Tstart, double Tstep) {
|
||||
|
||||
DKSTimer t;
|
||||
t.init("simulated annealing");
|
||||
t.start();
|
||||
|
||||
int ierr;
|
||||
double time_current;
|
||||
double time_next;
|
||||
|
||||
DKSSearchStates search(params_m);
|
||||
|
||||
//make a random guess
|
||||
search.initCurrentState();
|
||||
|
||||
//evaluate current state
|
||||
setParameterValues(search.getCurrentState());
|
||||
ierr = evaluateFunction(time_current);
|
||||
|
||||
if (ierr == DKS_ERROR)
|
||||
return;
|
||||
|
||||
for (double Temp = Tstart; Temp > 0; Temp -= Tstep) {
|
||||
|
||||
search.printCurrentState(time_current);
|
||||
|
||||
//calucate all the neighbours of current state
|
||||
search.getNeighbours(10);
|
||||
|
||||
//make a move to random neighbour and evaluate the runtime
|
||||
setParameterValues(search.getRandomNeighbour());
|
||||
ierr = evaluateFunction(time_next);
|
||||
|
||||
if (ierr == DKS_ERROR)
|
||||
return;
|
||||
|
||||
//if the solution improves move to this point else move to this point with probabily exp(-dE/T)
|
||||
if (time_next < time_current) {
|
||||
time_current = time_next;
|
||||
search.moveToNeighbour();
|
||||
} else {
|
||||
double p = (double)rand() / RAND_MAX;
|
||||
double dE = time_next - time_current;
|
||||
double P = exp(-dE/Temp);
|
||||
|
||||
if (P > p) {
|
||||
time_current = time_next;
|
||||
search.moveToNeighbour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
search.printCurrentState(time_current);
|
||||
|
||||
t.stop();
|
||||
std::cout << "Simulated annealing: " << t.gettime() << std::endl;
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user