improved ROUTINE insertion
This commit is contained in:
@@ -270,7 +270,7 @@ DEFNODECODE(ACC_CHECKSECTION_DIR, "%CMNT!DVM$%PUTTABCOMTHOSTSECTION%NL",
|
|||||||
's',0,BIFNODE)
|
's',0,BIFNODE)
|
||||||
DEFNODECODE(ACC_END_CHECKSECTION_DIR,"%CMNT!DVM$%PUTTABCOMTEND HOSTSECTION%NL",
|
DEFNODECODE(ACC_END_CHECKSECTION_DIR,"%CMNT!DVM$%PUTTABCOMTEND HOSTSECTION%NL",
|
||||||
's',0,BIFNODE)
|
's',0,BIFNODE)
|
||||||
DEFNODECODE(ACC_ROUTINE_DIR, "%CMNT!DVM$%PUTTABCOMTROUTINE%IF(%LL1!=%NULL), %LL1%NL",
|
DEFNODECODE(ACC_ROUTINE_DIR, "%CMNT!DVM$%PUTTABCOMTROUTINE%IF(%LL1!=%NULL), %LL1%ENDIF%NL",
|
||||||
's',1,BIFNODE)
|
's',1,BIFNODE)
|
||||||
DEFNODECODE(ACC_DECLARE_DIR, "%CMNT!DVM$%PUTTABCOMTDECLARE %LL1%NL",
|
DEFNODECODE(ACC_DECLARE_DIR, "%CMNT!DVM$%PUTTABCOMTDECLARE %LL1%NL",
|
||||||
's',1,BIFNODE)
|
's',1,BIFNODE)
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ typedef enum {
|
|||||||
DVMH_STAT_METRIC_CPY_HTOD,
|
DVMH_STAT_METRIC_CPY_HTOD,
|
||||||
DVMH_STAT_METRIC_CPY_DTOD,
|
DVMH_STAT_METRIC_CPY_DTOD,
|
||||||
/* DVMH memcpy */
|
/* DVMH memcpy */
|
||||||
|
DVMH_STAT_METRIC_CPY_ACROSS_DTOH,
|
||||||
|
DVMH_STAT_METRIC_CPY_ACROSS_HTOD,
|
||||||
|
DVMH_STAT_METRIC_CPY_ACROSS_DTOD,
|
||||||
DVMH_STAT_METRIC_CPY_SHADOW_DTOH,
|
DVMH_STAT_METRIC_CPY_SHADOW_DTOH,
|
||||||
DVMH_STAT_METRIC_CPY_SHADOW_HTOD,
|
DVMH_STAT_METRIC_CPY_SHADOW_HTOD,
|
||||||
DVMH_STAT_METRIC_CPY_SHADOW_DTOD,
|
DVMH_STAT_METRIC_CPY_SHADOW_DTOD,
|
||||||
@@ -86,6 +89,9 @@ static const char *dvmhStatMetricsTitles[DVMH_STAT_METRIC_FORCE_INT] = {
|
|||||||
"Copy GPU to CPU",
|
"Copy GPU to CPU",
|
||||||
"Copy CPU to GPU",
|
"Copy CPU to GPU",
|
||||||
"Copy GPU to GPU",
|
"Copy GPU to GPU",
|
||||||
|
"[Across] Copy GPU to CPU",
|
||||||
|
"[Across] Copy CPU to GPU",
|
||||||
|
"[Across] Copy GPU to GPU",
|
||||||
"[Shadow] Copy GPU to CPU",
|
"[Shadow] Copy GPU to CPU",
|
||||||
"[Shadow] Copy CPU to GPU",
|
"[Shadow] Copy CPU to GPU",
|
||||||
"[Shadow] Copy GPU to GPU",
|
"[Shadow] Copy GPU to GPU",
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ void DvmhRegionInserter::parFuncsInNode(LoopGraph *loop, bool isParallel)
|
|||||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
parallel_functions.insert(it->second);
|
parallel_functions[it->second].insert(loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -133,23 +133,36 @@ void DvmhRegionInserter::updateParallelFunctions(const map<string, vector<LoopGr
|
|||||||
while (changes_done)
|
while (changes_done)
|
||||||
{
|
{
|
||||||
changes_done = false;
|
changes_done = false;
|
||||||
set<FuncInfo*> newList;
|
map<FuncInfo*, set<LoopGraph*>> newList;
|
||||||
for (auto& funcPair : allFunctions)
|
for (auto& funcPair : allFunctions)
|
||||||
{
|
{
|
||||||
FuncInfo* func = funcPair.second;
|
FuncInfo* func = funcPair.second;
|
||||||
for (auto& callsTo : func->callsTo)
|
for (auto& callsTo : func->callsTo)
|
||||||
{
|
{
|
||||||
if (parallel_functions.find(callsTo) != parallel_functions.end() &&
|
auto itF = parallel_functions.find(func);
|
||||||
parallel_functions.find(func) == parallel_functions.end())
|
|
||||||
|
set<LoopGraph*> added;
|
||||||
|
if (itF != parallel_functions.end())
|
||||||
|
added = itF->second;
|
||||||
|
|
||||||
|
auto itTo = parallel_functions.find(callsTo);
|
||||||
|
if (itTo != parallel_functions.end())
|
||||||
|
{
|
||||||
|
for (auto& loop : itTo->second)
|
||||||
|
{
|
||||||
|
if (added.find(loop) == added.end())
|
||||||
{
|
{
|
||||||
newList.insert(func);
|
|
||||||
changes_done = true;
|
changes_done = true;
|
||||||
|
newList[func].insert(loop);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& newElem : newList)
|
for (auto& newElem : newList)
|
||||||
parallel_functions.insert(newElem);
|
for (auto& loop : newElem.second)
|
||||||
|
parallel_functions[newElem.first].insert(loop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,7 +1053,156 @@ static void insertInterface(SgStatement* func, const string& iface, const string
|
|||||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insertRoutine(SgStatement* func)
|
static LoopGraph* getParallelLoop(LoopGraph* loop)
|
||||||
|
{
|
||||||
|
auto prev_st = loop->loop->lexPrev();
|
||||||
|
|
||||||
|
while (prev_st && isDVM_stat(prev_st))
|
||||||
|
{
|
||||||
|
if (prev_st->variant() == DVM_PARALLEL_ON_DIR)
|
||||||
|
return loop;
|
||||||
|
prev_st = prev_st->lexPrev();
|
||||||
|
loop = loop->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static set<LoopGraph*> getParallelLoops(const std::set<LoopGraph*>& loops)
|
||||||
|
{
|
||||||
|
set<LoopGraph*> retVal;
|
||||||
|
for (auto& elem : loops)
|
||||||
|
{
|
||||||
|
string oldFile = current_file->filename();
|
||||||
|
if (!elem->loop->switchToFile())
|
||||||
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
|
auto parLoop = getParallelLoop(elem);
|
||||||
|
checkNull(parLoop, convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
retVal.insert(parLoop);
|
||||||
|
|
||||||
|
if (SgFile::switchToFile(oldFile) == -1)
|
||||||
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static set<DIST::Array*> getPrivateArrays(const set<LoopGraph*>& parLoops,
|
||||||
|
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||||
|
{
|
||||||
|
set<DIST::Array*> retVal;
|
||||||
|
|
||||||
|
for (auto& loop : parLoops)
|
||||||
|
{
|
||||||
|
string oldFile = current_file->filename();
|
||||||
|
if (!loop->loop->switchToFile())
|
||||||
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
|
for (auto& priv : loop->directive->privates)
|
||||||
|
{
|
||||||
|
bool isArray = false;
|
||||||
|
if (isArrayType(priv->type()))
|
||||||
|
{
|
||||||
|
auto type = isSgArrayType(priv->type());
|
||||||
|
if (type && type->dimension())
|
||||||
|
isArray = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isArray)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(priv), priv->identifier());
|
||||||
|
checkNull(arr, convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
|
set<DIST::Array*> realArrayRefs;
|
||||||
|
getRealArrayRefs(arr, arr, realArrayRefs, arrayLinksByFuncCalls);
|
||||||
|
|
||||||
|
for (auto& elem : realArrayRefs)
|
||||||
|
retVal.insert(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SgFile::switchToFile(oldFile) == -1)
|
||||||
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SgExpression* getPrivateArraysInPar(const FuncInfo* funcInfo, const std::set<LoopGraph*>& inLoops,
|
||||||
|
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||||
|
SgExpression* addedPrivList)
|
||||||
|
{
|
||||||
|
if (!funcInfo)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
map<string, SgExpression*> addedPriv;
|
||||||
|
SgExpression* ex = addedPrivList;
|
||||||
|
while (ex)
|
||||||
|
{
|
||||||
|
if (ex->lhs() && ex->lhs()->variant() == ACC_PRIVATE_OP)
|
||||||
|
{
|
||||||
|
ex = ex->lhs()->lhs();
|
||||||
|
while (ex)
|
||||||
|
{
|
||||||
|
if (ex->lhs() && ex->lhs()->variant() == VAR_REF)
|
||||||
|
addedPriv[ex->lhs()->symbol()->identifier()] = ex->lhs();
|
||||||
|
ex = ex->rhs();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ex = ex->rhs();
|
||||||
|
}
|
||||||
|
|
||||||
|
SgStatement* func = funcInfo->funcPointer->GetOriginal();
|
||||||
|
auto prog = isSgProgHedrStmt(func);
|
||||||
|
checkNull(prog, convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
|
set<LoopGraph*> inParLoops = getParallelLoops(inLoops);
|
||||||
|
set<DIST::Array*> privArrays = getPrivateArrays(inLoops, arrayLinksByFuncCalls);
|
||||||
|
|
||||||
|
for (int z = 0; z < prog->numberOfParameters(); ++z)
|
||||||
|
{
|
||||||
|
SgSymbol* par = prog->parameter(z);
|
||||||
|
bool isArray = false;
|
||||||
|
if (isArrayType(par->type()))
|
||||||
|
{
|
||||||
|
auto type = isSgArrayType(par->type());
|
||||||
|
if (type && type->dimension())
|
||||||
|
isArray = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArray && addedPriv.count(par->identifier()) == 0)
|
||||||
|
{
|
||||||
|
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(par), par->identifier());
|
||||||
|
checkNull(arr, convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
|
set<DIST::Array*> realArrayRefs;
|
||||||
|
getRealArrayRefs(arr, arr, realArrayRefs, arrayLinksByFuncCalls);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto& elem : realArrayRefs)
|
||||||
|
if (privArrays.find(elem) != privArrays.end())
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
addedPriv[par->identifier()] = new SgVarRefExp(par);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedPriv.size())
|
||||||
|
{
|
||||||
|
vector<SgExpression*> list;
|
||||||
|
for (auto& elem : addedPriv)
|
||||||
|
list.push_back(elem.second);
|
||||||
|
|
||||||
|
return makeExprList(list, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertRoutine(SgStatement* func, const FuncInfo* funcInfo, const std::set<LoopGraph*>& inLoops,
|
||||||
|
const map<DIST::Array*, set<DIST::Array*>>& arrayLinksByFuncCalls)
|
||||||
{
|
{
|
||||||
string oldFile = current_file->filename();
|
string oldFile = current_file->filename();
|
||||||
if (!func->switchToFile())
|
if (!func->switchToFile())
|
||||||
@@ -1048,26 +1210,34 @@ static void insertRoutine(SgStatement* func)
|
|||||||
|
|
||||||
SgStatement* st = func->lexNext();
|
SgStatement* st = func->lexNext();
|
||||||
SgStatement* last = func->lastNodeOfStmt();
|
SgStatement* last = func->lastNodeOfStmt();
|
||||||
bool has = false;
|
|
||||||
|
SgStatement* routine = NULL;
|
||||||
while (st != last)
|
while (st != last)
|
||||||
{
|
{
|
||||||
if (st->variant() == ACC_ROUTINE_DIR)
|
if (st->variant() == ACC_ROUTINE_DIR)
|
||||||
{
|
{
|
||||||
has = true;
|
routine = st;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
st = st->lexNext();
|
st = st->lexNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has == false)
|
if (!routine)
|
||||||
{
|
{
|
||||||
st = func->lexNext();
|
st = func->lexNext();
|
||||||
st->insertStmtBefore(*new SgStatement(ACC_ROUTINE_DIR), *st->controlParent());
|
routine = new SgStatement(ACC_ROUTINE_DIR);
|
||||||
|
st->insertStmtBefore(*routine, *st->controlParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
SgExpression* list = getPrivateArraysInPar(funcInfo, inLoops, arrayLinksByFuncCalls, routine->expr(0));
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
list = new SgExpression(EXPR_LIST, new SgExpression(ACC_PRIVATE_OP, list));
|
||||||
|
routine->setExpression(0, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SgFile::switchToFile(oldFile) == -1)
|
if (SgFile::switchToFile(oldFile) == -1)
|
||||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isPure(SgStatement* func)
|
static bool isPure(SgStatement* func)
|
||||||
@@ -1089,15 +1259,23 @@ void DvmhRegionInserter::createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo
|
|||||||
insertInterface(func->funcPointer, getInterfaceBlock(callFrom->funcPointer->GetOriginal(), callFrom->funcParams), callFrom->funcName);
|
insertInterface(func->funcPointer, getInterfaceBlock(callFrom->funcPointer->GetOriginal(), callFrom->funcParams), callFrom->funcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DvmhRegionInserter::createInterfaceBlockForParallelFunctions()
|
void DvmhRegionInserter::createInterfaceBlockForParallelFunctions(bool onlyRoutine)
|
||||||
{
|
{
|
||||||
for (auto& parF : parallel_functions)
|
for (auto& func_pair : parallel_functions)
|
||||||
{
|
{
|
||||||
|
const auto& parF = func_pair.first;
|
||||||
|
const auto& inLoops = func_pair.second;
|
||||||
|
|
||||||
for (auto& callTo : parF->callsTo)
|
for (auto& callTo : parF->callsTo)
|
||||||
{
|
{
|
||||||
if (callTo->fileName != parF->fileName && isPure(parF->funcPointer->GetOriginal()))
|
if (callTo->fileName != parF->fileName && isPure(parF->funcPointer->GetOriginal()))
|
||||||
{
|
{
|
||||||
insertRoutine(parF->funcPointer->GetOriginal());
|
if (onlyRoutine)
|
||||||
|
{
|
||||||
|
insertRoutine(parF->funcPointer->GetOriginal(), parF, inLoops, arrayLinksByFuncCalls);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto it = callTo->interfaceBlocks.find(parF->funcName);
|
auto it = callTo->interfaceBlocks.find(parF->funcName);
|
||||||
if (it == callTo->interfaceBlocks.end())
|
if (it == callTo->interfaceBlocks.end())
|
||||||
{
|
{
|
||||||
@@ -1124,7 +1302,7 @@ void DvmhRegionInserter::createInterfaceBlockForParallelFunctions()
|
|||||||
st->symbol()->identifier() == parF->funcName)
|
st->symbol()->identifier() == parF->funcName)
|
||||||
{
|
{
|
||||||
iface = st;
|
iface = st;
|
||||||
insertRoutine(iface);
|
insertRoutine(iface, parF, inLoops, arrayLinksByFuncCalls);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1362,15 +1540,16 @@ void insertDvmhRegions(SgProject& project, int files, const vector<ParallelRegio
|
|||||||
for (int i = files - 1, k = 0; i >= 0; --i, ++k)
|
for (int i = files - 1, k = 0; i >= 0; --i, ++k)
|
||||||
{
|
{
|
||||||
SgFile* file = &(project.file(i));
|
SgFile* file = &(project.file(i));
|
||||||
|
|
||||||
DvmhRegionInserter* regionInserter = inserters[k];
|
|
||||||
|
|
||||||
for (auto& func : regionInserter->getParallelFunctions())
|
|
||||||
createInterfacesForOutCalls(func);
|
|
||||||
|
|
||||||
// create interface for 'parallel' functions and
|
|
||||||
// insert ROUTINE directive if needed
|
// insert ROUTINE directive if needed
|
||||||
regionInserter->createInterfaceBlockForParallelFunctions();
|
inserters[k]->createInterfaceBlockForParallelFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = files - 1, k = 0; i >= 0; --i, ++k)
|
||||||
|
{
|
||||||
|
SgFile* file = &(project.file(i));
|
||||||
|
|
||||||
|
// create interface for 'parallel' functions
|
||||||
|
inserters[k]->createInterfaceBlockForParallelFunctions(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& regionInserter : inserters)
|
for (auto& regionInserter : inserters)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class DvmhRegionInserter
|
|||||||
bool isMpiProgram;
|
bool isMpiProgram;
|
||||||
|
|
||||||
ReadWriteAnalyzer& rw_analyzer;
|
ReadWriteAnalyzer& rw_analyzer;
|
||||||
std::set<FuncInfo*> parallel_functions;
|
std::map<FuncInfo*, std::set<LoopGraph*>> parallel_functions;
|
||||||
std::set<DIST::Array*> writesToArraysInParallelLoops;
|
std::set<DIST::Array*> writesToArraysInParallelLoops;
|
||||||
std::set<DIST::Array*> usedArraysInParallelLoops;
|
std::set<DIST::Array*> usedArraysInParallelLoops;
|
||||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
|
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
|
||||||
@@ -76,7 +76,7 @@ public:
|
|||||||
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
|
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
|
||||||
|
|
||||||
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
|
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
|
||||||
void createInterfaceBlockForParallelFunctions();
|
void createInterfaceBlockForParallelFunctions(bool onlyRoutine = true);
|
||||||
void removePrivatesFromParallelLoops();
|
void removePrivatesFromParallelLoops();
|
||||||
void addPrivatesToParallelLoops();
|
void addPrivatesToParallelLoops();
|
||||||
void addUsedArrays(std::set<DIST::Array*>& arrays);
|
void addUsedArrays(std::set<DIST::Array*>& arrays);
|
||||||
@@ -95,7 +95,12 @@ public:
|
|||||||
usedArraysInParallelLoops = newSet;
|
usedArraysInParallelLoops = newSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::set<FuncInfo*>& getParallelFunctions() const { return parallel_functions; }
|
const std::set<FuncInfo*> getParallelFunctions() const {
|
||||||
|
std::set<FuncInfo*> retVal;
|
||||||
|
for (auto& elem : parallel_functions)
|
||||||
|
retVal.insert(elem.first);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
|
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
|
||||||
static void createInterfaceBlockForOutCalls(FuncInfo* func);
|
static void createInterfaceBlockForOutCalls(FuncInfo* func);
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERSION_SPF "2375"
|
#define VERSION_SPF "2379"
|
||||||
|
|||||||
Reference in New Issue
Block a user