diff --git a/build/cmake/terrame/CMakeLists.txt b/build/cmake/terrame/CMakeLists.txt index b26a27de..ba049eca 100644 --- a/build/cmake/terrame/CMakeLists.txt +++ b/build/cmake/terrame/CMakeLists.txt @@ -127,6 +127,12 @@ source_group("Source Files\\observer\\types\\udpsender" FILES ${TERRAME_OBSERVER source_group("Header Files\\observer\\types\\udpsender" FILES ${TERRAME_OBSERVER_UDP_SENDER_HDR_FILES}) source_group("UI Files\\observer\\types\\udpsender" FILES ${TERRAME_OBSERVER_UDP_SENDER_UI_FILES}) +#terrame/src/hpa +file(GLOB TERRAME_HPA_SRC_FILES ${TERRAME_ABSOLUTE_ROOT_DIR}/src/hpa/*.cpp) +file(GLOB TERRAME_HPA_HDR_FILES ${TERRAME_ABSOLUTE_ROOT_DIR}/src/hpa/*.h) +source_group("Source Files\\hpa" FILES ${TERRAME_HPA_SRC_FILES}) +source_group("Header Files\\hpa" FILES ${TERRAME_HPA_HDR_FILES}) + if(APPLE) find_library(_COREFOUNDATION_LIBRARY NAMES CoreFoundation PATHS "/") @@ -292,7 +298,8 @@ set(TERRAME_FILES ${TERRAME_CORE_SRC_FILES} ${TERRAME_CORE_HDR_FILES} ${TERRAME_OBSERVER_TYPES_CHART_PLOT_SRC_FILES} ${TERRAME_OBSERVER_TYPES_CHART_PLOT_HDR_FILES} ${TERRAME_OBSERVER_TYPES_STATE_MACHINE_SRC_FILES} ${TERRAME_OBSERVER_TYPES_STATE_MACHINE_HDR_FILES} ${TERRAME_OBSERVER_UDP_SENDER_SRC_FILES} ${TERRAME_OBSERVER_UDP_SENDER_HDR_FILES} ${TERRAME_OBSERVER_UDP_SENDER_UI_FILES} - ${TERRAME_GEN_HDR_FILES} + ${TERRAME_HPA_SRC_FILES} ${TERRAME_HPA_HDR_FILES} + ${TERRAME_GEN_HDR_FILES} ${TERRAME_OBSERVER_QRC_FILES} ${TERRAME_OBSERVER_QRC_FILES_ADD} ${TERRAME_APP_ICON}) diff --git a/src/core/model.h b/src/core/model.h index 019e8f6f..769b54c0 100644 --- a/src/core/model.h +++ b/src/core/model.h @@ -35,12 +35,6 @@ of this software and its documentation. #include #include -#if defined(TME_WIN32) -#include -#else -//#include -#endif - using namespace std; typedef string ModelID; diff --git a/src/core/registryObjects.h b/src/core/registryObjects.h index ff585a2d..df2dfae6 100644 --- a/src/core/registryObjects.h +++ b/src/core/registryObjects.h @@ -396,5 +396,22 @@ Luna::RegType luaEnvironment::methods[] = {0, 0} }; +//****************************** HPA ****************************************// + +// Tiago - alterei as linhas baixo para tornar o HPA um lightuserdata que 'e imune ao garbage collector de Lua +const char HPA::className[] = "HPA"; + +Luna::RegType HPA::methods[] = +{ + method(HPA, joinall), + method(HPA, join), + method(HPA, parallel), + method(HPA, acquire), + method(HPA, release), + method(HPA, np), + method(HPA, HPATests), + {0, 0} +}; + #endif // REGISTRY_OBJECT_H diff --git a/src/core/terrameLua.cpp b/src/core/terrameLua.cpp index 57d79859..44bbcdc1 100644 --- a/src/core/terrameLua.cpp +++ b/src/core/terrameLua.cpp @@ -58,6 +58,8 @@ extern "C" #include "luna.h" #include "LuaBindingDelegate.h" +#include "hpa/hpa.h" + QApplication* app; ////////////////////////////////////////////////////////////////////////////// @@ -165,6 +167,7 @@ void registerClasses() Luna::getInstance()->setup(L); Luna::getInstance()->setup(L); Luna::getInstance()->setup(L); + Luna::getInstance()->setup(L); } int cpp_runcommand(lua_State *L) @@ -339,6 +342,16 @@ int cpp_closeAllWidgets(lua_State* L) return 0; } +int cpp_hpa_run(lua_State* L) +{ + std::string script = lua_tostring(L, -1); + HPA *HPAFlow = new HPA(script, L); + HPAFlow->execute(); + delete HPAFlow; + + return 0; +} + extern ExecutionModes execModes; int main(int argc, char *argv[]) @@ -457,6 +470,9 @@ int main(int argc, char *argv[]) lua_pushcfunction(L, cpp_closeAllWidgets); lua_setglobal(L, "cpp_closeAllWidgets"); + lua_pushcfunction(L, cpp_hpa_run); + lua_setglobal(L, "cpp_hpa_run"); + // Execute the lua files if (argc < 2) { @@ -481,6 +497,10 @@ int main(int argc, char *argv[]) argument++; } + //HPA *HPAFlow = new HPA("hpa_model_test.lua", L); + //HPAFlow->execute(); + //delete HPAFlow; + lua_call(L, 1, 0); } diff --git a/src/core/terrameLua5_1.h b/src/core/terrameLua5_1.h index cffdac67..f3a928b9 100644 --- a/src/core/terrameLua5_1.h +++ b/src/core/terrameLua5_1.h @@ -138,5 +138,7 @@ luaCell * findCell(luaCellularSpace*, CellIndex&); #include "luaTcpSender.h" #include "luaUdpSender.h" +#include "hpa/hpa.h" + #endif // TERRAME_LUA_5_1_H diff --git a/src/hpa/bagOfTasks.h b/src/hpa/bagOfTasks.h new file mode 100644 index 00000000..664775d6 --- /dev/null +++ b/src/hpa/bagOfTasks.h @@ -0,0 +1,87 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef BAG_OF_TASKS_H +#define BAG_OF_TASKS_H + +extern "C" { + #include +} + +#include +#include +#include +#include "paramsTask.h" + +using namespace std; + +static list BAG; + +static QMutex LOCK_BAG; + +static int bagOfTask(list *bag_, ParamTask *firtTask) { + LOCK_BAG.lock(); + //neste caso sai um resultado para ser tratado no run (preciso refatorar aqui) + if(bag_->empty()) + { + LOCK_BAG.unlock(); + return 0; + } + else + { + firtTask = &bag_->front(); + bag_->pop_front(); + } + LOCK_BAG.unlock(); + return 1; +} + +//para obter quantidade de tasks agurdando execucao +static int bagSize(list *bag_){ + int nTasks; + LOCK_BAG.lock(); + nTasks = bag_->size(); + LOCK_BAG.unlock(); + return nTasks; +} + +static void bagInsertion(list *bag_, string toExec, string nameFunc, vector params, vector returns, lua_State* storeVals){ + LOCK_BAG.lock(); + + ParamTask toIncludeBagP; + toIncludeBagP.setCallTask(toExec); + toIncludeBagP.setNameTask(nameFunc); + toIncludeBagP.setSetParam(params); + toIncludeBagP.setSetRet(returns); + + if(params.size() == 0) + lua_close(storeVals); + else + toIncludeBagP.set_State(storeVals); + + bag_->push_back(toIncludeBagP); + + LOCK_BAG.unlock(); +} + +#endif diff --git a/src/hpa/envHPA.h b/src/hpa/envHPA.h new file mode 100644 index 00000000..6b4f3aa0 --- /dev/null +++ b/src/hpa/envHPA.h @@ -0,0 +1,238 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef ENV_HPA +#define ENV_HPA + +#include +#include +#include +#include "luna.h" + +#include + +using namespace std; + +/////////////////////////////////////////////////////////////////////////VAR's GLOBAIS//////////////////////////////////////////////////// + +//tenho que ver como tratar isso aqui (primeira solucao para o carrinho de rolima andar... :D) + +//modelo do usua'rio a ser executado luaState +static lua_State *ModeloMain; + +//quantidade de nu'cleos da ma'quina que esta sendo utilizada +static int numCPU; + +static QMutex LOCK_ACESS; + +//1p tentativa de controle de varia'veis globais +//QHash Table_VarGlobal; + +///////////////////////////////////////////////////////////////////////////TOOLS//////////////////////////////////////////////////////////// +//metodo S. Tokenizen para utilizaao no parser +static void S_Tokenize(const string& linha, vector& tokens, const string& delimitadores = " ") { + string::size_type lastPos = linha.find_first_not_of(delimitadores, 0); + string::size_type pos = linha.find_first_of(delimitadores, lastPos); + + //tentar otimizar aqui + while (string::npos != pos || string::npos != lastPos) { + tokens.push_back(linha.substr(lastPos, pos - lastPos)); + lastPos = linha.find_first_not_of(delimitadores, pos); + pos = linha.find_first_of(delimitadores, lastPos); + } +} + +#define LOAD_BUF_SIZE (10 * 1024) +struct load_buf +{ + unsigned char* cur; + unsigned char* buf; +}; + +static int writer(lua_State* L, const void* b, long size, void* B) +{ + load_buf* buf = (load_buf*)B; + //assert(LOAD_BUF_SIZE - (buf->cur - buf->buf) >= size); + memcpy(buf->cur, b, size); + buf->cur += size; + return 1; +} + +static const char* reader(lua_State* L, void* ud, size_t* size) +{ + load_buf* buf = (load_buf*)ud; + *size = buf->cur - buf->buf; + return (const char*)buf->buf; +} + +//geral exceto para table +static int HPAxcopy_aux(lua_State *Principal, lua_State *To_Stack, int idx) +{ + switch (lua_type(Principal, idx)) + { + case LUA_TNIL: + lua_pushnil(To_Stack); + break; + case LUA_TBOOLEAN: + lua_pushboolean(To_Stack, lua_toboolean(Principal, idx)); + break; + case LUA_TNUMBER: + lua_pushnumber(To_Stack, lua_tonumber(Principal, idx)); + break; + case LUA_TSTRING: + lua_pushlstring(To_Stack, lua_tostring(Principal, idx), lua_rawlen(Principal, idx)); + break; + case LUA_TLIGHTUSERDATA: + lua_pushlightuserdata(To_Stack, (void*)lua_touserdata(Principal, idx)); + break; + default: + //tem que ver como sao os tipos de Tiago + break; + } + return 1; +} + +//troca de paramtros entre pilhas de execucao +static int HPAxcopy(lua_State *Principal, lua_State *To_Stack, int idx) +{ + int top; + lua_newtable(To_Stack); + top = lua_gettop(To_Stack); + lua_pushnil(Principal); + + while (lua_next(Principal, idx) != 0) { + HPAxcopy_aux(Principal, To_Stack, -2); + //tabela de tabela de ... + if (lua_type(Principal, -1) == LUA_TTABLE) + HPAxcopy(Principal, To_Stack, lua_gettop(Principal)); + else + HPAxcopy_aux(Principal, To_Stack, -1); + + //if para possivel tratamento + if(lua_type(To_Stack, top) == LUA_TTABLE) + lua_settable(To_Stack, top); + + lua_pop(Principal, 1); + } + return 1; +} + +static void hpaLoadParams(lua_State *now, vectorPar, lua_State *now_par) { + //para inserir estas variaveis para a funcao que deve ser executada + string my_var; + string name_Var; + bool is_global = false; + + //Espace_MAIN.acquire(1); + + for (int co = 0; co < Par.size(); co++) { + name_Var = Par[co]; + //apenas para conversao dos contadores de cada novo parametro + char aaux[BUFSIZ]; + + #ifdef WIN32 + //para windows + itoa((co + 1), aaux, 10); + #else + //para linux(falta itoa) + sprintf (aaux, "%ld", (co + 1)); + #endif + + string aux = aaux; + + my_var = "__HPA_VAR__" + aux; + + //verifico se a variavel esta na pilha auxiliar de parametros + lua_getglobal(now_par, name_Var.c_str()); + if(lua_type(now_par, -1) != 0) + is_global = true; + + if (is_global) { + is_global = false; + + //tentar acessar os valores da variavel na piha principal do lua + lua_getglobal(now_par, name_Var.c_str()); + + if(lua_type(now_par, -1) != LUA_TTABLE) + { + HPAxcopy_aux(now_par, now, -1); + } + else + { + //todo tipo de tiago tem este identficador + lua_getglobal(now_par, (name_Var + "_is_ref").c_str()); + + //se e tipo de tiago vamso so mover + if(lua_type(now_par, -1) != 0){ + lua_pop(now_par, 1); + lua_xmove(now_par, now, 1); + }else{ + lua_pop(now_par, 1); + //tenho que verificar se e' tipo de tiago se for preciso usar x_move + HPAxcopy(now_par, now, -2); + } + } + + lua_setglobal(now, my_var.c_str()); + //luaL_loadstring(now, ("local " + my_var + " = " + my_var).c_str()); + //string changePrior = "local "+my_var+"="+my_var; + //luaL_dostring(now, changePrior.c_str()); + //luaL_dostring(now, changePrior.c_str()); +// luaL_ref(now, LUA_REGISTRYINDEX); + + } else { + //my_var = "local "+my_var + "="; + my_var = my_var + "="; + my_var = my_var + name_Var; + luaL_dostring(now, my_var.c_str()); + } + } + + //Espace_MAIN.release(1); +} + +/////////////////////////////////////////////////////////////////////////ENV///////////////////////////////////////////////////////////////// + +//metodos para manipular a quantidade de threads que o hpa ira utilizar para a execucao do modelo (sera' possi'vel alterar utilizando diretiva) +static int getNumCpu(){ + return numCPU; +} + +static void setNumCpu(int numCpu_){ + numCPU = numCpu_; +} + +//metodos para acesso e manipulacao da pilha principal do modelo +static void setMainStack(lua_State* ModeloMain_){ + ModeloMain = ModeloMain_; +} + +static lua_State* getMainStack(){ + return ModeloMain; +} + +//////////////////////////////////////////////////////////////////////LOCK/////////////////////////////////////////////////////////////////// + +static QMutex lockAcess; + +#endif diff --git a/src/hpa/hpa.cpp b/src/hpa/hpa.cpp new file mode 100644 index 00000000..a2216f02 --- /dev/null +++ b/src/hpa/hpa.cpp @@ -0,0 +1,564 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#include "hpa.h" + +#ifdef WIN32 + #include +#elif __linux__ + #include +#endif + +void HPA::createWorkers(){ + //lua_settop(ModeloMain, 0); + //lua_gc(ModeloMain, LUA_GCCOLLECT, 0); + + //iniciando os workers + for(int i = 0; i < getNumCpu(); i++){ + workers.push_back(new ProcTask()); // tiago - outra fonte de leak! + workers.at(workers.size()-1)->set_State(lua_newthread(ModeloMain)); + workers.at(workers.size()-1)->setRefThread(luaL_ref(ModeloMain, LUA_REGISTRYINDEX)); + //setamos aqui o recurso compartilhado entre o processo principal hpa e os trabalhadores + //(e' preciso efetuar o controle de acesso as tasks) + workers.at(workers.size()-1)->setBag(&BAG); + workers.at(workers.size()-1)->setControlQMut(&LOCK_BAG); + lua_gc(workers.at(workers.size()-1)->getState(), LUA_GCSTOP, 0); + } +} + +// Tiago - Metodo do Saulo que eu considerei muito mal implementdo, entao comentei e fiz o meu a seguir +// void HPA::removeWorkers(lua_State *L){ +// for(int i = 0; i < getNumCpu(); i++){ +// luaL_unref(L, workers.at(i)->getRefThread(), LUA_REGISTRYINDEX); + +// // Tiago -- necessario para remover leak de memoria geraso pelo saulo +// if (workers[i]) delete workers[i]; +// } + +// workers.clear(); +// workers = vector(); // Tiago - nao faco ideia do que esta linha faz. Atribuindo um objeto local ao atributo da classe, para mim vai dar PROBLEMA! +// // Mais doido ainda quando vemos que o vetor workers eh estatico' +// } + +void HPA::removeWorkers(lua_State *L){ + vector::iterator it; + + for(it = workers.begin(); it != workers.end(); it++){ + luaL_unref(L, (*it)->getRefThread(), LUA_REGISTRYINDEX); + + // Tiago -- necessario para remover leak de memoria geraso pelo saulo + delete *it; + } + + workers.clear(); +} + +void HPA::removeLockSections( void ){ + QHash::iterator it; + + for (it = lockSection.begin(); it != lockSection.end(); ++it) delete it.value(); + + lockSection.clear(); + lockSectionUse.clear(); +} + +HPA::HPA(lua_State* L){ +// +// ModeloMain = L; +// mainStack = new ProcHPA(); // Tiago - fonte de leak +// +// mainStack->set_State(ModeloMain); +// +//#ifdef WIN32 +// //informacao sobre a quantidade de cores da maquina +// SYSTEM_INFO sysinfo; +// GetSystemInfo(&sysinfo); +// setNumCpu(sysinfo.dwNumberOfProcessors); +//#else +// int numberOfProcessors = sysconf(_SC_NPROCESSORS_ONLN); +// setNumCpu(numberOfProcessors); +//#endif +// +// createWorkers(); +// string pathModel = "D:/terrame/tests/hpa_model_test.lua"; +// qWarning(pathModel.c_str()); +// mainStack->setNameTranslated(pathModel.c_str()); +// qWarning("construtor HPA - fim"); +// //removendo todos os restos de conversao do path principal +// //parser->cleanTranslate(); + +////////////////////////////////////////////////////////////////////////////////////// + + refGlobalHPA = luaL_ref(L, LUA_REGISTRYINDEX); + + luaL_dostring(L, "__T__"); // Tiago - achei que isto era codigo que o Saulo usou para debug e esqueceu de apagar, mas se tirar estas linha tudo para de funcionar + + int temp = luaL_ref(L, LUA_REGISTRYINDEX); // Tiago - achei que isto era codigo que o Saulo usou para debug e esqueceu de apagar, , mas se tirar estas linha tudo para de funcionar + + //aqui setamos o recurso compartilhado para o processo ou a pilha principal(dessa forma economizamos memo'ria) + setBag(&BAG); + setControlQMut(&LOCK_BAG); + + // Tiago - linha necessaria para resolver leak + mainStack = NULL; + + //luaL_unref(L, LUA_REGISTRYINDEX, temp); +} + +// Tiago -- comentei pq nao estava em uso +// HPA::HPA(string pathModel){ +// ParserHPA *parser = new ParserHPA(pathModel); + +// mainStack = new ProcHPA(); +// ModeloMain = luaL_newstate(); + +// //esta aqui e' a pilha principal(ela efetua as chamadas) +// mainStack->set_State(ModeloMain); + +// //informacao sobre a quantidade de cores da maquina +// #if defined ( TME_WIN32 ) +// SYSTEM_INFO sysinfo; +// GetSystemInfo(&sysinfo); +// setNumCpu(sysinfo.dwNumberOfProcessors); +// #else +// int numberOfProcessors = sysconf( _SC_NPROCESSORS_ONLN ); +// setNumCpu(numberOfProcessors); +// #endif + +// createWorkers(); + +// luaL_openlibs(mainStack->getState()); + +// //esse aqui e' o novo modelo a ser executado (aqui ele ja' esta traduzido) +// pathModel = parser->getNewPath(); + +// Luna::Register(mainStack->getState()); + +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); + +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); + +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); +// //registrar logo na cahamada dessa pilha +// Luna::Register(mainStack->getState()); + +// Luna::Register(mainStack->getState()); +// Luna::Register(mainStack->getState()); + +// mainStack->setNameTranslated(pathModel); + +// //removendo todos os restos de conversao do path principal +// //parser->cleanTranslate(); +// } + +HPA::HPA(string pathModel, lua_State *L){ + //ParserHPA *parser = new ParserHPA(pathModel); // Tiago - fonte de leak + //esta aqui e' a pilha principal(ela efetua as chamadas) + ModeloMain = L; + mainStack = new ProcHPA(); // Tiago - fonte de leak + + mainStack->set_State(ModeloMain); + + #ifdef WIN32 + //informacao sobre a quantidade de cores da maquina + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + setNumCpu(sysinfo.dwNumberOfProcessors); + #else + int numberOfProcessors = sysconf( _SC_NPROCESSORS_ONLN ); + setNumCpu(numberOfProcessors); + #endif + + createWorkers(); + + //esse aqui e' o novo modelo a ser executado (aqui ele ja' esta traduzido) + //pathModel = //"D:/terrame/tests/hpa_model_test.lua"; //parser->getNewPath(); + mainStack->setNameTranslated(pathModel.c_str()); + //removendo todos os restos de conversao do path principal + //parser->cleanTranslate(); + + // Tiago -- removendo leaks de memoria gerados pelo Saulo + //delete parser; +} + +// Tiago -- estava tentando remover leaks de memoria gerados pelo Saulo +// mas o codigo abaixo nao funcionou, parece que o HPA roda como variavel statica pq "this" tem sempre o mesmo valor +// e quando a pilha lua e' fehada por "lua_close()" no main(), o codigo abaixo gera um "segmentation fault" +// tive que fazer mainStack = NULL no construtor HPA( lusState*) chamado por lua +HPA::~HPA(){ + if(mainStack) + { + if( mainStack->getState()) + removeWorkers(mainStack->getState()); + removeLockSections(); + delete mainStack; + } + else // so o objeto HPA criado em Lua tem referencia e nao tem mainStack + { + luaL_unref(L, LUA_REGISTRYINDEX, refGlobalHPA); + } +} + +int HPA::execute(){ + //execucao da thread aqui + mainStack->start(); + mainStack->wait(); + return true; +} + +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_JOINALL(lua_State* L){ +int HPA::joinall(lua_State* L){ + while(!Bag->empty()){ + for (int i = 0; i < getNumCpu(); i++) { + if (!workers.at(i)->isRunning() && !Bag->empty()) + workers.at(i)->start(); + } + + for (int i = 0; i < getNumCpu(); i++){ + if (workers.at(i)->isRunning()) + workers.at(i)->wait(); + } + } + + for (int i = 0; i < getNumCpu(); i++){ + if (!workers.at(i)->isRunning() && !Bag->empty()) + workers.at(i)->start(); + } + + for (int i = 0; i < getNumCpu(); i++){ + if (workers.at(i)->isRunning()) + workers.at(i)->wait(); + } + + /* + if(lua_status(L) != 0 && lua_status(L) != 1){ + cerr << "error in main stack \n"; + }*/ + + return 0; +} + +//me'todo para setar quantidade de cores a serem utilizados na execucao(para testes TDD) +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_NP(lua_State* L){ +int HPA::np(lua_State* L){ + int newQuantProc = lua_tonumber(L, 1); + + if(!newQuantProc || (newQuantProc == numCPU)) + { + lua_pushinteger(L, numCPU); + return 1; + } + //e' preciso esperar todas as threads terminarem pois estas serao destrui'das para a criacao de novas + HPA::joinall(L); + + removeWorkers(L); + numCPU = newQuantProc; + + createWorkers(); + return 0; +} + +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_Acquire(lua_State *L){ +int HPA::acquire(lua_State *L){ + int temp_par = lua_tonumber(L, 1); + + char resultConvert[16]; + sprintf(resultConvert, "%d", temp_par); + string nameSec = resultConvert; + + justOne.lock(); + + //aqui entra a parte de verificacao na HASH principal + if(!lockSection.contains(nameSec.c_str())){ + lockSection.insert(nameSec.c_str(), new QMutex()); // Tiago -- esse mutex vai gerar leak + } + + justOne.unlock(); + + lockSection[nameSec.c_str()]->lock(); + + return 0; +} + +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_Release(lua_State *L){ +int HPA::release(lua_State *L){ + int temp_par = lua_tonumber(L, 1); + + char resultConvert[16]; + sprintf(resultConvert, "%d", temp_par); + string nameSec = resultConvert; + + justOne.lock(); + lockSection[nameSec.c_str()]->unlock(); + justOne.unlock(); + + return 0; +} + +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_JOIN(lua_State* L){ +int HPA::join(lua_State* L){ + string nameFuncJoin = lua_tostring(L, 1); + + //dos workers que estao executando existe algum qeu esta a executar esta funcao? + for(int i = 0; i < workers.size(); i++){ + if(!workers.at(i)->getName().compare(nameFuncJoin)){ + workers.at(i)->wait(); + } + } + + bool thereATask = false; + //agora preciso verificar se a bag recebeu alguma chamada dessa funcao + + justOne.lock(); + int sizeBag = Bag->size(); + + for (std::list::iterator it = Bag->begin(); it != Bag->end(); it++){ + if(!it->getNameTask().compare(nameFuncJoin)){ + thereATask = true; + break; + } + } + justOne.unlock(); + + //existe processo na bag com este nome e temos que aguardar a sua execucao + if(thereATask){ + for(int i = 0; i < workers.size(); i++){ + workers.at(i)->wait(); + } + } + + if(lua_status(L) != 0 && lua_status(L) != 1){ + cerr << "error in main stack \n"; + } + + return 0; +} + +//metodo auxiliar para o TerraMEHPA para leitura dos parametros de entrada da chamada paralela +lua_State* HPA::Read_Parameters(lua_State* L, vectorname_of_par){ + //estado que vai armezanar temporariamente o valor dos parametros + lua_State *store_val = luaL_newstate(); + + //percorrer cada parametro + int positionOfParam = 2; + + //leitura deve ser realizada aqui passar por todos os parametros + for(int ind = 0; ind < name_of_par.size(); ind++){ + if(lua_type(L, positionOfParam) != LUA_TTABLE) + { + HPAxcopy_aux(L, store_val, positionOfParam); + } + else + { + //todo tipo de tiago para aqui + lua_getfield(L, -1, "cObj_"); + + //caso em que tenho um cellular space + if(lua_type(L, -1) == 7) + { + //para este caso preciso inserir uma variavel de controle onde possa + //consultar para efetuar o xmove + luaL_dostring(store_val, (name_of_par[ind]+"_is_ref = 1").c_str()); + + lua_pop(L, 1); + lua_xmove(L, store_val, 1); + } + else + { + lua_pop(L, 1); + HPAxcopy(L, store_val, positionOfParam); + } + } + + lua_setglobal(store_val, name_of_par[ind].c_str()); + //luaL_ref(store_val, LUA_REGISTRYINDEX); + positionOfParam++; + } + + return store_val; +} + +vector HPA::findNamePar(string toExecut){ + vector executeClean; + vector namesPar; + + S_Tokenize(toExecut, executeClean, "( , )"); + + for(int i = 1; i < executeClean.size(); i++){ + if(i == executeClean.size()-1){ + if(executeClean.at(i).compare("; ")){ + namesPar.push_back(executeClean.at(i)); + } + }else{ + namesPar.push_back(executeClean.at(i)); + } + } + + return namesPar; +} + +string HPA::findNameFunc(string toExecut){ + vector executeClean; + + S_Tokenize(toExecut, executeClean, "("); + + if(executeClean.empty()){ + exit(0); + return ""; + } + + return executeClean.at(0); +} + +// Tiago - comentei linha abaixo para manter coerencia com a nomenclarura adotada no TerraME +//int HPA::HPA_PARALLEL(lua_State* L){ +int HPA::parallel(lua_State* L){ + int q_paramet = lua_gettop(L); + + //aqui vem a chamada da funcao e seus parametros + string to_execute = lua_tostring(L, 1); + + //chamada do metodo para tratar o retorno de resultado aqui (to_execute) + //Sera' implementado posteriormente uma vez que ainda e' preciso pensar em Cena'rios para esta antes de implementar (TDD) + + //funcao para reconhecer os respectivos nomes dos parametros passados (retornamos um vetor com os nomes) + vector namesOfPar = findNamePar(to_execute); + + //nome da funcao que sera executa (caso em que temos retorno isso aqui vai alterar) + string nameFuncToExec = findNameFunc(to_execute); + + //declaracao de um vetor para retorno da funcao (o tratamento da chamada da funcao deve aqui) + vector varReturn; + + //insercao na bag aqui para baixo (mudanca agora na insercao do nome da funcao a que a task corresponde) + //stack com o valor dos parametros para serem passados + lua_State *tempStackVals = Read_Parameters(L, namesOfPar); + + //bagInsertion(to_execute, nameFuncToExec, namesOfPar, varReturn, tempStackVals); + + //isso aqui faz parte do metodo de baginsertion + lock_bag->lock(); + + ParamTask toIncludeBagP; + toIncludeBagP.setCallTask(to_execute); + toIncludeBagP.setNameTask(nameFuncToExec); + toIncludeBagP.setSetParam(namesOfPar); + toIncludeBagP.setSetRet(varReturn); + + if(namesOfPar.size() == 0) + lua_close(tempStackVals); + else + toIncludeBagP.set_State(tempStackVals); + + Bag->push_back(toIncludeBagP); + lock_bag->unlock(); + + //fim do metodo insertion aqui + + //aqui verificamos se existe algum worker parado e efetuamos a inicializacao de algum deles para tratar a requisicao caso algum esteja ocioso + for(int i = 0; i < workers.size(); i++){ + if(!workers.at(i)->isRunning()){ + workers.at(i)->start(); + break; + } + } + + return 0; +} + +lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + + *arg = 0; + return L; +} + +int HPA::HPATests(lua_State * now){ + //string s = lua_tostring(now, 1); + /* + lua_newtable(now); + lua_pushinteger(now, 1337); + lua_setfield(now, -2, "tablekey"); + lua_setfield(now, LUA_REGISTRYINDEX, "mynewtable"); + */ + /* + lua_Debug luaDebug; + lua_getstack(now, 0, &luaDebug); + lua_setlocal(now, &luaDebug, 0); + */ + + lua_pushinteger(now, 98); + lua_setglobal(now, "teste"); + lua_getglobal(now, "teste"); + + int arg; + lua_State *L1 = getthread(now, &arg); + lua_Debug ar; + + if (!lua_getstack(L1, luaL_checkinteger(now, arg+1), &ar)) + return luaL_argerror(now, arg+1, "level out of range"); + + luaL_checkany(now, arg+3); + lua_settop(now, arg+3); + lua_xmove(now, L1, 1); + lua_pushstring(now, lua_setlocal(L1, &ar, luaL_checkinteger(now, arg+2))); + + return 1; + + //luaL_dostring(now, "teste = 10"); + //lua_pushinteger(now, 10); + //return 1; +} + +//metodos para setar e acessar os recursos da bag +void HPA::setBag(list* Bag_){ + Bag = Bag_; +} + +void HPA::setControlQMut(QMutex* controlMutex_){ + lock_bag = controlMutex_; +} + +list* HPA::getBag(){ + return Bag; +} + +QMutex* HPA::getControlQMut(){ + return lock_bag; +} diff --git a/src/hpa/hpa.h b/src/hpa/hpa.h new file mode 100644 index 00000000..3573b0f5 --- /dev/null +++ b/src/hpa/hpa.h @@ -0,0 +1,118 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef HPA_H +#define HPA_H + +#include "procHPA.h" +#include "procTask.h" +#include "envHPA.h" + +#include +#include +#include +#include + +#include "bagOfTasks.h" + +extern "C"{ + //#include + #include + #include + #include +} +#include "luna.h" + +using namespace std; + +//vetor de trabalhadores (minhas threads) +static vector workers; + +class HPA { + int refGlobalHPA; + +public: + //para seguir o template do Luna + static const char className[]; + static Luna::RegType methods[]; + +private: + //pilha de execucao principal + ProcHPA *mainStack; + string pathModel; + + list *Bag; + QMutex *lock_bag; + + //Hash para criacao das secoes criticas lembrar de utilizalos com o wait condition + QHash lockSection; + QHash lockSectionUse; + QMutex justOne; + + void createWorkers(); + void removeWorkers(lua_State *); + void removeLockSections(void); // Tiago - remover leak + lua_State* Read_Parameters(lua_State*, vector); + vector findNamePar(string); + string findNameFunc(string toExecut); + + //metodos para acessar e setar a bag para fora(public, like interface) para o controle de acesso tambe'm uma vez + //que ele e' compartilhado + void setBag(list*); + void setControlQMut(QMutex* controlMutex); + + list* getBag(); + QMutex* getControlQMut(); + + //QHash getLockSec(); + //QHash getLockSecUse(); + //QMutex controlAcess(); + +public: + //contrutor HPA, e' preciso passar como parametro o modelo instrumentado com as diretivas + //metodo apenas para ref no lua + + // HPA(string pathModel); // Tiago -- comentei pq nao estva em uso + HPA(string pathModel, lua_State *); + int execute(); + + //--------------------------implementacao das diretivas-------------------------- + //Executa o Join em todas as funcoes que estao executando ate' o ponto de chamada + HPA(lua_State *L); + + int joinall(lua_State*); + //Executa o Join na/nas funcoes name_func que esta/estao executando + int join(lua_State*); + //Corresponde a adicionar mais uma tarefa ao Bag of Task's para ser resolvida + int parallel(lua_State*); + //metodos para controlar acesso synchronized as variaveis globais + int acquire(lua_State *now); + int release(lua_State *now); + int np(lua_State *now); + + int HPATests(lua_State * now); + + ~HPA(); //Tiago -- necessario para resolver leaks de memoria gerado pelo Saulo +}; + +#endif diff --git a/src/hpa/paramsTask.cpp b/src/hpa/paramsTask.cpp new file mode 100644 index 00000000..75c5d047 --- /dev/null +++ b/src/hpa/paramsTask.cpp @@ -0,0 +1,106 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#include "paramsTask.h" + +#include + +ParamTask::ParamTask(){ + paramsOfCall = vector(); + paramsOfReturn = vector(); + //store_val = luaL_newstate(); + refOfReturn = 0; +} + +ParamTask::~ParamTask(){ + paramsOfCall.clear(); + paramsOfReturn.clear(); + nameFuncTask.clear(); + codeCall.clear(); + refOfReturn = NULL; +} + +//apenas uma insercao no vetor de parametros +void ParamTask::setParamCall(string param_){ + this->paramsOfCall.push_back(param_); +} + +//apenas uma insercao no vetor de parametros +void ParamTask::setCallTask(string callTask_){ + this->codeCall = callTask_; +} + +//apenas uma insercao no vetor de retorno de uma funcao +void ParamTask::setParamRet(string param_){ + this->paramsOfReturn.push_back(param_); +} + +string ParamTask::getCallTask(){ + return this->codeCall; +} + +//apenas acesso a um elemento do vetor de parametro +string ParamTask::getParamCall(int position_){ + return paramsOfCall.at(position_); +} + +//apenas acesso a um elemento do vetor de retorno +string ParamTask::getParamRet(int position_){ + return paramsOfReturn.at(position_); +} + +//e' possi'vel definir um conjunto de parametros por atribuicao (isso vai substituir todos os adicionados anteriormente) +void ParamTask::setSetParam(vector SetParams_){ + this->paramsOfCall = SetParams_; +} + +// +void ParamTask::setSetRet(vector SetReturns_){ + this->paramsOfReturn = SetReturns_; +} + +//e' possi'vel obter toda a lista de parametros +vector ParamTask::getSetParam(){ + return paramsOfCall; +} + +//retorna toda a lista de retorno(quais varia'veis vao ser atribuidas) +vector ParamTask::getSetRet(){ + return paramsOfReturn; +} + +lua_State* ParamTask::get_State(){ + return store_val; +} + +void ParamTask::set_State(lua_State* store_val_){ + this->store_val = store_val_; +} + +string ParamTask::getNameTask(){ + return nameFuncTask; +} + +void ParamTask::setNameTask(string nameTask_){ + this->nameFuncTask = nameTask_; +} diff --git a/src/hpa/paramsTask.h b/src/hpa/paramsTask.h new file mode 100644 index 00000000..079d934c --- /dev/null +++ b/src/hpa/paramsTask.h @@ -0,0 +1,99 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef PARAMS_TASK +#define PARAMS_TASK + +#include +#include + +extern "C"{ + #include +} + +#include "luna.h" + +#include + +using namespace std; + +class ParamTask{ +private: + //chamada da task igual a pilha principal + string codeCall; + + vector paramsOfCall; + vector paramsOfReturn; + string nameFuncTask; + //int ID_by_executed; + //local onde o retorno da funcao eecutada em paralelo deve ser empilhado + int refOfReturn; + //State em que se encontram os parametros que seram passados para o metodo + //tava com problema em pegar os parametros antigos + lua_State *store_val; + +public: + ParamTask(); + + ~ParamTask(); + + //insercao da chamada da funcao, como foi feita na pilha principal + void setCallTask(string param_); + + //apenas uma insercao no vetor de parametros + void setParamCall(string param_); + + //apenas uma insercao no vetor de retorno de uma funcao + void setParamRet(string param_); + + //chamada da funcao, como foi feita na pilha principal + string getCallTask(); + + //apenas acesso a um elemento do vetor de parametro + string getParamCall(int position_); + + //apenas acesso a um elemento do vetor de retorno + string getParamRet(int position_); + + //e' possi'vel definir um conjunto de parametros por atribuicao (isso vai substituir todos os adicionados anteriormente) + void setSetParam(vector SetParams_); + + // + void setSetRet(vector SetReturns_); + + //e' possi'vel obter toda a lista de parametros + vector getSetParam(); + + //retorna toda a lista de retorno(quais varia'veis vao ser atribuidas) + vector getSetRet(); + + lua_State* get_State(); + + void set_State(lua_State*); + + string getNameTask(); + + void setNameTask(string nameTask); +}; + +#endif diff --git a/src/hpa/procHPA.cpp b/src/hpa/procHPA.cpp new file mode 100644 index 00000000..e2df878d --- /dev/null +++ b/src/hpa/procHPA.cpp @@ -0,0 +1,116 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#include "procHPA.h" +#include "envHPA.h" + +extern char* TME_PATH; // Tiago + +//#define TME_WIN32 + +extern "C" +{ + #include + #include + #include +} + +#include "luna.h" + +ProcHPA::ProcHPA(){ + funcLua = luaL_newstate(); + luaL_openlibs(funcLua); +} + +void ProcHPA::set_State(lua_State *now) { + //qual lua state deve estar sendo executado + lua_close(this->funcLua); + this->funcLua = now; +} + +lua_State* ProcHPA::getState(){ + return this->funcLua; +} + +void ProcHPA::setNameTranslated(string _name) { + //nome da funcao que vai ser executada + this->nameTranslatedModel = _name; +} + +string ProcHPA::getNameTranslated(){ + return nameTranslatedModel; +} + +void ProcHPA::run(){ + luaL_dostring(funcLua, "__HPA_MODEL_ID_ = 0; "); + //olhar esta chamada + int erroTrad = luaL_loadfile(funcLua, nameTranslatedModel.c_str()); + if(erroTrad) + { + string msg = lua_tostring(funcLua, -1); + size_t firstPos = msg.find_first_of(":"); + size_t lastPos = msg.find_first_of(":", firstPos+1); + string originalLineNumber = msg.substr(firstPos+1, (lastPos-firstPos)-1); + int lineNumber = atoi(originalLineNumber.c_str()) - 1; + char newLineNumber[10]; + sprintf(newLineNumber, "%d", lineNumber); + string newMsg = nameTranslatedModel; + #ifdef WIN32 + int fileNamePos = nameTranslatedModel.find_last_of("\\"); + #else + int fileNamePos = nameTranslatedModel.find_last_of("/"); + #endif + newMsg = newMsg + ":" + newLineNumber + ":" + msg.substr(lastPos+1); + newMsg.erase(fileNamePos+1, 4); + + cerr << "Error: " << erroTrad << " msg: \n" << msg << "\n" << firstPos << ", " << lastPos << ", " << originalLineNumber << ", " << lineNumber << "\n" << newMsg << endl; + } + + // Tiago - Comente a linha abaixo se quiser ver o codigo traduzido + //remove(nameTranslatedModel.c_str()); + + //aqui ja' tenho a execucao do modelo principal + if (lua_pcall(funcLua, 0, 0, 0)) + { + string msg = lua_tostring(funcLua, -1); + //size_t firstPos = msg.find_first_of(":"); + //size_t lastPos = msg.find_first_of(":", firstPos+1); + //string originalLineNumber = msg.substr(firstPos+1, (lastPos-firstPos)-1); + //int lineNumber = atoi(originalLineNumber.c_str()) - 1; + //char newLineNumber[10]; + //sprintf(newLineNumber, "%d", lineNumber); + //string newMsg = nameTranslatedModel; + #ifdef WIN32 + int fileNamePos = nameTranslatedModel.find_last_of("\\"); + #else + int fileNamePos = nameTranslatedModel.find_last_of("/"); + #endif + //newMsg = newMsg + ":" + newLineNumber + ":" + msg.substr(lastPos+1); + string newMsg = msg; + newMsg.erase(fileNamePos+1, 4); + } + /* + lua_getglobal(funcLua, "SAULO"); + cerr << lua_tointeger(funcLua, -1) << endl; + */ +} diff --git a/src/hpa/procHPA.h b/src/hpa/procHPA.h new file mode 100644 index 00000000..52b8bba3 --- /dev/null +++ b/src/hpa/procHPA.h @@ -0,0 +1,80 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef PROC_HPA_H +#define PROC_HPA_H + +#include +#include +#include +#include "luna.h" + +#include "luaNeighborhood.h" +#include "luaCell.h" +#include "luaCellularSpace.h" + +#include "luaEvent.h" +#include "luaMessage.h" +#include "luaTimer.h" + +#include "luaAgent.h" +#include "luaTrajectory.h" +#include "luaGlobalAgent.h" +#include "luaLocalAgent.h" +#include "luaRule.h" +#include "luaJumpCondition.h" +#include "luaFlowCondition.h" +#include "luaControlMode.h" +#include "luaEnvironment.h" + +using namespace std; + +// Tiago - comentario +// A classe ProcHPA implementar o processo master da arquitetura TerraME HPA +// Ele executa a pilha principal do modelo lua e gerencia o trabalho dos workers. +class ProcHPA : public QThread { +private: + //estado da funcao/modelo que vai ser executada (entrada da chamada externa) + lua_State *funcLua; + //nome do modelo traduzido + string nameTranslatedModel; + +public: + ProcHPA(); + + //quando uma funcao terminou + void set_State(lua_State *Func); + + lua_State* getState(); + + //nome da funcao que esta sendo executada (para controle do join) + string getNameTranslated(); + + //qual a pro'xima funcao a ser executada (lembre-se que esttou tentando fazer reuso das instancias de worker's) + void setNameTranslated(string); + + //Thread + virtual void run(); +}; + +#endif //PROC_HPA_H diff --git a/src/hpa/procTask.cpp b/src/hpa/procTask.cpp new file mode 100644 index 00000000..4dfa6c1c --- /dev/null +++ b/src/hpa/procTask.cpp @@ -0,0 +1,248 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#include "procTask.h" +#include "envHPA.h" + +ProcTask::ProcTask(){ + isRunning_ = 0; +} + +void ProcTask::set_State(lua_State *now) { + //qual lua state deve estar sendo executado + this->funcLua = now; +} + +lua_State* ProcTask::getState(){ + return funcLua; +} + +void ProcTask::setName(string _name) { + //nome da funcao que vai ser executada + this->nameFunc = _name; +} + +string ProcTask::getName(){ + return nameFunc; +} + +//acesso dos vetores com os respectivos parametros para a execucao +vector ProcTask::getParamOfCham(){ + return this->paramOfCham; +} + +vector ProcTask::getParamOfReturn(){ + return this->paramOfReturn; +} + +//set parametros para execucao e para retorno +void ProcTask::setParamOfCham(vector paramOfCham_){ + this->paramOfCham = paramOfCham_; +} + +void ProcTask::setParamOfReturn(vector paramOfRet_){ + this->paramOfReturn = paramOfReturn; +} + +int ProcTask::getRunState(){ + return isRunning_; +} + +void ProcTask::setRefThread(int refThread_){ + this->refThread = refThread_; +} + +int ProcTask::getRefThread(){ + return this->refThread; +} + +void ProcTask::setRunState(int runState_){ + this->isRunning_ = runState_; +} + +void ProcTask::w_stack(){ + QTime now; + double calc_t; + //for(int ind = 0; ind < this->n_execute_clock; ind++) + for(int ind = 0; ind < 1000; ind++) + calc_t = QTime::currentTime().toString().toDouble(); +} + +void ProcTask::setParms(vector param_of_cham_, vector param_of_return_, int ID_by_executed_, int ref_of_return_, lua_State* store_val_){ + //tilizamos os valores setados pois nao e' necessa'rio acessar a bag para este + //use_Params_Set = true; + + this->paramOfCham = param_of_cham_; + this->paramOfReturn = param_of_return_; + + //local onde o retorno da funcao eecutada em paralelo dev ser dado + //Sualo refactoring verificar passagem destes parametros no HPA + //this->refOfReturn = ref_of_return_; + + //State em que se encontram os parametros que seram passados para o metodo + //tava com problema em pegar os parametros antigos + this->storeVal = store_val_; +} + +void ProcTask::setParms(vector param_of_cham_, vector param_of_return_, int ID_by_executed_, lua_State* store_val_){ + //tilizamos os valores setados pois nao e' necessa'rio acessar a bag para este + //use_Params_Set = true; + + this->paramOfCham = param_of_cham_; + this->paramOfReturn = param_of_return_; + + //State em que se encontram os parametros que seram passados para o metodo + //tava com problema em pegar os parametros antigos + this->storeVal = store_val_; +} + +void ProcTask::run() { + bool just_one = false; + + //thread comecou a consumir + this->isRunning_ = 1; + + while(!Bag->empty()){ + lock_bag->lock(); + + if(Bag->size() <= getNumCpu()){ + just_one = true; + } + + ParamTask tempParam; + + //SAULO + //bagOfTask(tempParam); + //neste caso sai um resultado para ser tratado no run (preciso refatorar aqui) + + if(Bag->empty()){ + lock_bag->unlock(); + return; + }else{ + tempParam = Bag->front(); + //primeira task a ser tratada + Bag->pop_front(); + } + //lock_bag->unlock(); + + //lockAcess.lock(); + this->setName(tempParam.getNameTask()); + + //tenho que tentar liberar a memoria gasta para temp_Param.store_val + if (tempParam.getSetParam().size() > 0) { + hpaLoadParams(funcLua, tempParam.getSetParam(), tempParam.get_State()); + lua_settop(tempParam.get_State(), 0); + //fechamento ocorre so' aqui (uma vez, se a pilha nao recebe parametros ela nao e' declarada) + lua_close(tempParam.get_State()); + } + + lua_getglobal(funcLua, this->nameFunc.c_str()); +//lua_Debug ar; // Tiago +//lua_getinfo(funcLua, ">n", &ar); // Tiago +//qWarning("Aqui"); +//qWarning(ar.name); +//char buffer[10]; +//sprintf(buffer, "%d" , ar.currentline); +//qWarning(buffer); + + for(int ind = 0; ind < tempParam.getSetParam().size(); ind++){ + string par_Now = "__HPA_VAR__"; + char C_aux_par[BUFSIZ]; + + #ifdef WIN32 + //para windows + itoa(ind+1, C_aux_par, 10); + #else + //para linux(nao existe itoa em linux) + sprintf (C_aux_par, "%ld", (ind+1)); + #endif + + string S_aux_par = C_aux_par; + par_Now += S_aux_par; + lua_getglobal(getState(), par_Now.c_str()); + } + + //lockAcess.unlock(); + lock_bag->unlock(); + + //lua_call(funcLua, tempParam.getSetParam().size(), 1); + int that_ok = lua_resume(this->funcLua, this->funcLua, tempParam.getSetParam().size()); //(funcLua, tempParam.getSetParam().size(), 1); + + lockAcess.lock(); + //QMutexLocker locker(&lockAcess); + + //chamada de um metodo de return entra agora + if(tempParam.getSetRet().size() > 0){ + //voltar a versao antiga + /*lua_getref(Execute_HPA->MAIN->Func_Lua, temp_Param.ref_of_return); + lua_xmove(Func_Lua, Execute_HPA->MAIN->Func_Lua, temp_Param.param_of_return.size()); + lua_unref(Execute_HPA->MAIN->Func_Lua, temp_Param.ref_of_return); */ + hpaLoadParams(getState(), tempParam.getSetRet(), tempParam.get_State()); + }else{ + //necessito retirar a chamada da funcao do topo + lua_pop(getState(), 1); + } + + lua_settop(getState(), 0); + + //lua_gc(getState(), LUA_GCSTOP, 0); + + //qualquer estado diferebte exige desalocacao e temos que construir uma nova co-routine + if(lua_status(getState()) != 0 && lua_status(getState()) != 1 && that_ok != 0 && that_ok != 1){ + //if(lua_status(getState()) != 0 && lua_status(getState()) != 1){ + //lua_Debug ar; // Tiago + //int erron = lua_getstack(getState(), 1, &ar ); // Tiago + //lua_getinfo(getState(), "n", &ar); // Tiago + cerr << "Verify the call just below the directive hpa parallel, named: " << this->nameFunc.c_str() << endl; //- near to " << ar.name << ar.source << ":"<< ar.currentline << ":"<< " defined at line:"<< ar.linedefined << endl; // Tiago + cerr.flush(); + lua_yield(getState(), 0); + //lua_settop(Func_Lua, 0); + luaL_unref(getState(), getRefThread(), LUA_REGISTRYINDEX); + set_State(lua_newthread(ModeloMain)); + setRefThread(luaL_ref(ModeloMain, LUA_REGISTRYINDEX)); + } + + lockAcess.unlock(); + if(just_one){ + break; + } + } + setRunState(0); +} + +//metodos para setar e acessar os recursos da bag +void ProcTask::setBag(list* Bag_){ + Bag = Bag_; +} + +void ProcTask::setControlQMut(QMutex* controlMutex_){ + lock_bag = controlMutex_; +} + +list* ProcTask::getBag(){ + return Bag; +} + +QMutex* ProcTask::getControlQMut(){ + return lock_bag; +} diff --git a/src/hpa/procTask.h b/src/hpa/procTask.h new file mode 100644 index 00000000..fb7772b6 --- /dev/null +++ b/src/hpa/procTask.h @@ -0,0 +1,115 @@ +/************************************************************************************ +TerraME - a software platform for multiple scale spatially-explicit dynamic modeling. +Copyright (C) 2001-2017 INPE and TerraLAB/UFOP -- www.terrame.org + +This code is part of the TerraME framework. +This framework is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library. + +The authors reassure the license terms regarding the warranties. +They specifically disclaim any warranties, including, but not limited to, +the implied warranties of merchantability and fitness for a particular purpose. +The framework provided hereunder is on an "as is" basis, and the authors have no +obligation to provide maintenance, support, updates, enhancements, or modifications. +In no event shall INPE and TerraLAB / UFOP be held liable to any party for direct, +indirect, special, incidental, or consequential damages arising out of the use +of this software and its documentation. +*************************************************************************************/ + +#ifndef PROC_TASK_H +#define PROC_TASK_H + +extern "C"{ + #include +} + +//#include +#include + +#include "paramsTask.h" +#include "bagOfTasks.h" + +using namespace std; + +// Tiago - comentario +// A classe ProcTask implementa os workers da arquitetura TerraME HPA +class ProcTask : public QThread { +private: + //estado da funcao/modelo que vai ser executada + lua_State *funcLua; + + //nome da funcao que foi chamada + string nameFunc; + + //parametros de chamada da task + vector paramOfCham; + + //variaveis de retorno da task + vector paramOfReturn; + + int refOfReturn; + //State em que se encontram os parametros que seram passados para o metodo + //tava com problema em pegar os parametros antigos + lua_State *storeVal; + + int isRunning_; + + //referencia para enganar garbage collector + int refThread; + + list *Bag; + + QMutex *lock_bag; + +public: + ProcTask(); + + //quando um a funcao terminou + void set_State(lua_State *Func); + + lua_State* getState(); + + //nome da funcao + string getName(); + + //nome da nova funcao a ser executada + void setName(string); + + //parametros para a execucao da pro'xima funcao + void setParms(vector, vector, int, int, lua_State*); + void setParms(vector, vector, int, lua_State*); + + vector getParamOfCham(); + vector getParamOfReturn(); + + void setParamOfCham(vector paramOfCham_); + void setParamOfReturn(vector paramOfReturn_); + + void w_stack(); + + //thread + void run(); + + //set o estado corrente da task em execucao + void setRunState(int runState_); + + int getRunState(); + + void setRefThread(int ref_); + int getRefThread(); + + //metodos para acessar e setar a bag para fora(public, like interface) para o controle de acesso tambe'm uma vez + //que ele e' compartilhado + void setBag(list*); + void setControlQMut(QMutex* controlMutex); + + list* getBag(); + QMutex* getControlQMut(); +}; + +#endif //PROC_HPA_H diff --git a/src/lua/terrame.lua b/src/lua/terrame.lua index 1086be1c..8c0ff7c6 100644 --- a/src/lua/terrame.lua +++ b/src/lua/terrame.lua @@ -984,7 +984,7 @@ function _Gtme.loadTmeFile(luafile) end local function runScript(script) - if info_.mode ~= "quiet" then + if info_.mode ~= "quiet" and not info_.hpa then --TODO: hap doesn't work whit mode ~= quiet local mt = getmetatable(_G) _Gtme.checkNilVariables(mt) end @@ -1023,7 +1023,13 @@ local function runScript(script) end end - local success, result = _Gtme.myxpcall(function() dofile(tostring(script)) end) + local success, result + if info_.hpa then + success, result = _Gtme.myxpcall(function() cpp_hpa_run(tostring(script)) end) + else + success, result = _Gtme.myxpcall(function() dofile(tostring(script)) end) + end + if not success then _Gtme.printError(result) os.exit(1) @@ -1622,6 +1628,8 @@ function _Gtme.execute(arguments) -- 'arguments' is a vector of strings local numIssues = _Gtme.checkPackage(package, pkgPath) os.exit(numIssues) + elseif arg == "-hpa" then + info_.hpa = true else _Gtme.printError("Option not recognized: '"..arg.."'.") os.exit(1) diff --git a/test/commands.lua b/test/commands.lua index 56e533da..17fee154 100644 --- a/test/commands.lua +++ b/test/commands.lua @@ -186,3 +186,9 @@ sketch = { base = {arg = "-sketch"} } +hpa = { + basic = {script = "hpa-basic.lua", arg = "-hpa"}, + sum = {script = "hpa-matrix-sum.lua", arg = "-hpa"}, + multiplication = {script = "hpa-matrix-mult.lua", arg = "-hpa"} +} + diff --git a/test/log/hpa-basic.log b/test/log/hpa-basic.log new file mode 100644 index 00000000..ecaa9b4e --- /dev/null +++ b/test/log/hpa-basic.log @@ -0,0 +1,190 @@ +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok +start bank test... +Ok +start bank test with join function... +Ok +start PI calculate... +Ok +start sum stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start foo stress on critical section access... +Ok +start different number of parameters... +Ok +start changing number of workers... +Ok +Ok +start return conditions... +Ok diff --git a/test/log/hpa-multiplication.log b/test/log/hpa-multiplication.log new file mode 100644 index 00000000..bb036d78 --- /dev/null +++ b/test/log/hpa-multiplication.log @@ -0,0 +1,21 @@ +number of processors: 1 +setup elapsed time (parallel): 0.011 +setup elapsed time (total): 0.368 +multiplication elapsed time (parallel): 21.657 +multiplication elapsed time (total): 21.838 +mult granularity elapsed time (parallel): 20.851 +mult granularity elapsed time (total): 21.036 +number of processors: 2 +setup elapsed time (parallel): 0.007 +setup elapsed time (total): 0.389 +multiplication elapsed time (parallel): 12.582 +multiplication elapsed time (total): 12.798 +mult granularity elapsed time (parallel): 13.137 +mult granularity elapsed time (total): 13.330 +number of processors: 3 +setup elapsed time (parallel): 0.006 +setup elapsed time (total): 0.357 +multiplication elapsed time (parallel): 11.406 +multiplication elapsed time (total): 11.587 +mult granularity elapsed time (parallel): 10.103 +mult granularity elapsed time (total): 10.266 diff --git a/test/log/hpa-sum.log b/test/log/hpa-sum.log new file mode 100644 index 00000000..0bb13d57 --- /dev/null +++ b/test/log/hpa-sum.log @@ -0,0 +1,15 @@ +number of processors: 1 +setup elapsed time (parallel): 0.242 +setup elapsed time (total): 8.370 +sum elapsed time (parallel): 2.361 +sum elapsed time (total): 4.534 +number of processors: 2 +setup elapsed time (parallel): 0.156 +setup elapsed time (total): 9.059 +sum elapsed time (parallel): 1.868 +sum elapsed time (total): 4.564 +number of processors: 3 +setup elapsed time (parallel): 0.144 +setup elapsed time (total): 7.937 +sum elapsed time (parallel): 1.507 +sum elapsed time (total): 3.675 diff --git a/test/run.lua b/test/run.lua index bc4a25ee..3db17b01 100644 --- a/test/run.lua +++ b/test/run.lua @@ -151,6 +151,7 @@ local function approximateLine(line) if string.match(line, "Creating") then return 120 end if string.match(line, "Building") then return 8 end if string.match(line, "should contain only") then return 1 end + if string.match(line, "elapsed time") then return 6 end return 0 end diff --git a/test/scripts/hpa-basic.lua b/test/scripts/hpa-basic.lua new file mode 100644 index 00000000..d250f806 --- /dev/null +++ b/test/scripts/hpa-basic.lua @@ -0,0 +1,341 @@ +local hpa = HPA() + +local function bank() + local pbalance = 0 + local balance = 0 + local transactions = {} + local ntrans = 100 + + for i = 1, ntrans do + table.insert(transactions, math.random(-10, 10)) + end + + function pDepOrDeb(idx) + hpa:acquire("id") + pbalance = pbalance + transactions[idx] + hpa:release("id") + end + + function DepOrDeb(idx) + balance = balance + transactions[idx] + end + + print("start bank test...") + + for idx = 1, ntrans do + hpa:parallel("pDepOrDeb(idx)", idx) + end + hpa:joinall() + + for idx = 1, ntrans do + DepOrDeb(idx) + end + + if(pbalance == balance)then + print("Ok") + else + print("error: "..pbalance.." ~= "..balance) + end + io.flush() +end + +local function calcPI() + local insideCircle = 0 + local pInsideCircle = 0 + local nexecs = 1000000 + local cpus = 2 + local posX = {} + local posY = {} + local p1 = 0 + local p2 = 0 + + for i = 1, nexecs do + table.insert(posX, math.random()) + table.insert(posY, math.random()) + end + + function ppi(initial,final) + for i = initial, final do + if ((posX[i]*posX[i]) + (posY[i]*posY[i])) <= 1 then + hpa:acquire(1) + pInsideCircle = pInsideCircle + 1 + hpa:release(1) + end + end + end + + function pi() + for ind = 1, nexecs do + local x = posX[ind] + local y = posY[ind] + if ((x*x)+(y*y)) <= 1 then + insideCircle = insideCircle + 1 + end + end + end + + print("start PI calculate...") + l1 = math.floor(nexecs/2); + l2 = l1+1 + + local splitInt = math.floor(nexecs/cpus) + local start = 1 + local finish = splitInt + + while(finish <= nexecs) do + hpa:parallel("ppi(start,finish)", start, finish) + start = finish + 1 + finish = finish + splitInt + end + hpa:joinall() + + pi() + + local presult = 4*(pInsideCircle/nexecs) + local result = 4*(insideCircle/nexecs) + + if presult == result then + print("Ok") + else + print("error") + end + + io.flush() +end + +local function stress1() + local t = 0 + local cpus = 2 + local loops = 100000 + + function sum() + for i = 1, loops do + hpa:acquire(1) + t = t + 1 + hpa:release(1) + end + end + + print("start sum stress on critical section access...") + for i = 1, cpus do + hpa:parallel("sum()") + end + hpa:joinall() + + if t == loops * cpus then + print("Ok") + else + print("error") + end + io.flush() +end + +local function stress2() + local cpus = 2 + + function foo() + local t = 0 + local loops = 100000 + + for i = 1, loops do + t = i + hpa:acquire(t) + local x = t + i + hpa:release(t) + end + end + + print("start foo stress on critical section access...") + for i = 1, cpus do + hpa:parallel("foo()") + end + hpa:joinall() + print("Ok") + io.flush() +end + +local function stress3() + local verifyVector = {} + local loops = 100000 + local cpus = 2 + + for i = 1, loops do + table.insert(verifyVector, 0) + end + + function foo() + local t = 0 + for j = 1, #verifyVector do + for i = 1, 1 do + t = i + hpa:acquire(j) + verifyVector[j] = verifyVector[j] + j + hpa:release(j) + end + end + end + + print("start foo stress on critical section access...") + for a = 1, cpus do + hpa:parallel("foo()") + end + hpa:joinall() + + local verif = false + for i = 1, loops do + if(verifyVector[i] ~= (i * cpus)) then + verif = true + break + end + end + + if verif == true then + print("error") + else + print("Ok") + end + io.flush() +end + +local function parameters() + local sum = 0 + function par1(p1) + sum = sum + p1 + end + + function par2(p1, p2) + sum = sum + p1 + p2 + end + + function par3(p1, p2, p3) + sum = sum + p1 + p2 + p3 + end + + print("start different number of parameters...") + hpa:parallel("par1(p1)", 1) + hpa:parallel("par2(p1, p2)", 1, 2) + hpa:parallel("par3(p1, p2, p3)", 1, 2, 3) + hpa:joinall() + if sum == 10 then + print("Ok") + io.flush() + else + print("parameters sum error: "..sum) + end + +end + +local function workers() + local loops = 100000 + function foo() + local temp = 0 + for i = 1, 100 do + temp = temp + i/temp+1; + end + end + + print("start changing number of workers...") + io.flush() + + local np = hpa:np() + hpa:np(1) + for i = 1, loops do + hpa:parallel("foo()") + end + hpa:joinall() + print("Ok") + io.flush() + + hpa:np(2) + for i = 1, loops do + hpa:parallel("foo()") + end + hpa:joinall() + print("Ok") + io.flush() + hpa:np(np) +end + +local function returns() + function foo3(j,i) + hpa:acquire(1) + local aux = {} + local x, y = foo2() + hpa:release(1) + return x + end + + function foo2() + return 1, 2 + end + + function foo1(j) + for i = 1, 100 do + foo3(j, i) + end + end + + print("start return conditions...") + for i = 1, 10 do + hpa:parallel("foo1(i)", i) + end + hpa:joinall() + print("Ok") + io.flush() + collectgarbage() +end + +local function bankJoin() + local pbalance = 0 + local balance = 0 + local transactions = {} + local ntrans = 100 + + for i = 1, ntrans do + table.insert(transactions, math.random(-10, 10)) + end + + function pDepOrDeb(idx) + hpa:acquire("id") + pbalance = pbalance + transactions[idx] + hpa:release("id") + end + + function DepOrDeb(idx) + balance = balance + transactions[idx] + end + + print("start bank test with join function...") + + for idx = 1, ntrans do + hpa:parallel("pDepOrDeb(idx)", idx) + end + + hpa:join("pDepOrDeb") + + -- only for test a funtion that not exists + hpa:join("FuncNExist") + + for idx = 1, ntrans do + DepOrDeb(idx) + end + + if(pbalance == balance)then + print("Ok") + else + print("error: "..pbalance.." ~= "..balance) + end + io.flush() +end + +for n = 1, 10 do + bank() + bankJoin() + calcPI() + stress1() + stress2() + stress3() + parameters() + workers() + returns() +end \ No newline at end of file diff --git a/test/scripts/hpa-matrix-mult.lua b/test/scripts/hpa-matrix-mult.lua new file mode 100644 index 00000000..8ae38bcd --- /dev/null +++ b/test/scripts/hpa-matrix-mult.lua @@ -0,0 +1,129 @@ +local hpa = HPA() + +local function setup(np, dim) + local t0 = os.clock() + + local csA = CellularSpace { + xdim = dim + } + + local csB = CellularSpace { + xdim = dim + } + + function fillCsA() + forEachCell(csA, function(cell) + cell.value = dim + end) + end + + function fillCsB() + forEachCell(csB, function(cell) + cell.value = dim + end) + end + + hpa:np(np) + + local t1 = os.clock() + + hpa:parallel("fillCsA()") + hpa:parallel("fillCsB()") + hpa:joinall() + + io.flush() + local t2 = os.clock() + + print(string.format("setup elapsed time (parallel): %.3f", t2 - t1)) + print(string.format("setup elapsed time (total): %.3f", t2 - t0)) + + return csA, csB +end + +local function matrixMultiplication(np, dim, csA, csB) + local t0 = os.clock() + + hpa:np(np) + + local res = CellularSpace { + xdim = dim + } + + function multiply(i, j) + res:get(i, j).value = 0 + for k = 0, dim - 1 do + res:get(i, j).value = res:get(i, j).value + + csA:get(i, k).value * csB:get(k, j).value + end + end + + local t1 = os.clock() + + for i = 0, dim - 1 do + for j = 0, dim - 1 do + hpa:parallel("multiply(i, j)", i, j) + end + end + + hpa:joinall() + + io.flush() + local t2 = os.clock() + + print(string.format("multiplication elapsed time (parallel): %.3f", t2 - t1)) + print(string.format("multiplication elapsed time (total): %.3f", t2 - t0)) + return res:sample().value +end + +local function matrixMultiplicationGranularity(np, dim, csA, csB) + local t0 = os.clock() + + hpa:np(np) + + local res = CellularSpace { + xdim = dim + } + + function multiply(i) + for j = 0, dim - 1 do + res:get(i, j).value = 0 + for k = 0, dim - 1 do + res:get(i, j).value = res:get(i, j).value + + csA:get(i, k).value * csB:get(k, j).value + end + end + end + + local t1 = os.clock() + + for i = 0, dim - 1 do + hpa:parallel("multiply(i)", i) + end + + hpa:joinall() + + io.flush() + local t2 = os.clock() + + print(string.format("mult granularity elapsed time (parallel): %.3f", t2 - t1)) + print(string.format("mult granularity elapsed time (total): %.3f", t2 - t0)) + return res:sample().value +end + +local np = hpa:np() - 1 -- time increase using all processors +if np > 3 then np = 3 end +local dim = 150 + +for n = 1, np do + print("number of processors: "..n) + local csA, csB = setup(n, dim) + local sample1 = matrixMultiplication(n, dim, csA, csB) + collectgarbage("collect") + local sample2 = matrixMultiplicationGranularity(n, dim, csA, csB) + collectgarbage("collect") + if sample1 ~= sample2 then + print("Error", sample1, sample2) + os.exit(1) + end +end + diff --git a/test/scripts/hpa-matrix-sum.lua b/test/scripts/hpa-matrix-sum.lua new file mode 100644 index 00000000..aba1a64f --- /dev/null +++ b/test/scripts/hpa-matrix-sum.lua @@ -0,0 +1,112 @@ +local hpa = HPA() + +local function setupToSum(np, dim) + local t0 = os.clock() + + local csA = CellularSpace { + xdim = dim + } + + local csB = CellularSpace { + xdim = dim + } + + local csC = CellularSpace { + xdim = dim + } + + local csD = CellularSpace { + xdim = dim + } + + function fillCsA() + forEachCell(csA, function(cell) + cell.value = dim + end) + end + + function fillCsB() + forEachCell(csB, function(cell) + cell.value = dim + end) + end + + function fillCsC() + forEachCell(csC, function(cell) + cell.value = dim + end) + end + + function fillCsD() + forEachCell(csD, function(cell) + cell.value = dim + end) + end + + hpa:np(np) + + local t1 = os.clock() + + hpa:parallel("fillCsA()") + hpa:parallel("fillCsB()") + hpa:parallel("fillCsC()") + hpa:parallel("fillCsD()") + hpa:joinall() + + io.flush() + local t2 = os.clock() + + print(string.format("setup elapsed time (parallel): %.3f", t2 - t1)) + print(string.format("setup elapsed time (total): %.3f", t2 - t0)) + + return csA, csB, csC, csD +end + +local function matrixSum(np, dim, csA, csB, csC, csD) + local t0 = os.clock() + + local res = CellularSpace { + xdim = dim + } + + function sum(i) + for j = 0, dim - 1 do + res:get(i, j).value = csA:get(i, j).value + csB:get(i, j).value + + csC:get(i, j).value + csD:get(i, j).value + end + end + + hpa:np(np) + + local t1 = os.clock() + + for i = 0, dim - 1 do + hpa:parallel("sum(i)", i) + end + + hpa:joinall() + + io.flush() + local t2 = os.clock() + + print(string.format("sum elapsed time (parallel): %.3f", t2 - t1)) + print(string.format("sum elapsed time (total): %.3f", t2 - t0)) + + return res:sample().value +end + +local np = hpa:np() - 1 -- time increase using all processors +if np > 3 then np = 3 end +local dim = 500 + +for n = 1, np do + print("number of processors: "..n) + local csA, csB, csC, csD = setupToSum(n, dim) + collectgarbage("collect") + local sample = matrixSum(n, dim, csA, csB, csC, csD) + collectgarbage("collect") + if sample ~= 4*dim then + print("Error", sample, 4*dim) + os.exit(1) + end +end