finalyze moving
This commit is contained in:
236
src/Distribution/Array.cpp
Normal file
236
src/Distribution/Array.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "Array.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static vector<pair<int, int>> applyNewOrder(const vector<pair<int, int>>& in, const vector<int>& newOrder)
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
countOfDepr += (in[z].first == 0 && in[z].second == 0) ? 1 : 0;
|
||||
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() + countOfDepr != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
vector<pair<int, int>> tmp, retTmp(newOrder.size());
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
if (!(in[z].first == 0 && in[z].second == 0))
|
||||
tmp.push_back(in[z]);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retTmp[z] = tmp[newOrder[z]];
|
||||
|
||||
vector<pair<int, int>> retVal;
|
||||
for (int z = 0, z1 = 0; z < in.size(); ++z)
|
||||
if ((in[z].first == 0 && in[z].second == 0))
|
||||
retVal.push_back(in[z]);
|
||||
else
|
||||
retVal.push_back(retTmp[z1++]);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static vector<int> applyNewOrder(const vector<int> &in, const vector<int> &newOrder)
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
countOfDepr += (in[z] == -1) ? 1 : 0;
|
||||
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() + countOfDepr != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
vector<int> tmp, retTmp(newOrder.size());
|
||||
for (int z = 0; z < in.size(); ++z)
|
||||
if (in[z] != -1)
|
||||
tmp.push_back(in[z]);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retTmp[z] = tmp[newOrder[z]];
|
||||
|
||||
vector<int> retVal;
|
||||
for (int z = 0, z1 = 0; z < in.size(); ++z)
|
||||
if (in[z] == -1)
|
||||
retVal.push_back(in[z]);
|
||||
else
|
||||
retVal.push_back(retTmp[z1++]);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static vector<T> applyNewOrderS(const vector<T> &in, const vector<int> &newOrder)
|
||||
{
|
||||
vector<T> retVal(in.size());
|
||||
if (newOrder.size() == 0)
|
||||
return in;
|
||||
if (newOrder.size() != in.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
retVal[z] = in[newOrder[z]];
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
vector<pair<int, int>> TemplateLink::GetAlignRules() const
|
||||
{
|
||||
vector<pair<int, int>> retVal = alignRuleWithTemplate;
|
||||
if (templateArray == NULL)
|
||||
return retVal;
|
||||
|
||||
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
|
||||
if (newOrder.size() == 0)
|
||||
return alignRuleWithTemplate;
|
||||
else
|
||||
return applyNewOrder(retVal, newOrder);
|
||||
}
|
||||
|
||||
vector<int> TemplateLink::GetLinks() const
|
||||
{
|
||||
vector<int> retVal = linkWithTemplate;
|
||||
if (templateArray == NULL)
|
||||
return retVal;
|
||||
|
||||
vector<int> newOrder = templateArray->GetNewTemplateDimsOrder();
|
||||
if (newOrder.size() == 0)
|
||||
return linkWithTemplate;
|
||||
else
|
||||
return applyNewOrder(retVal, newOrder);
|
||||
}
|
||||
|
||||
string TemplateLink::toString() const
|
||||
{
|
||||
string retVal = "";
|
||||
|
||||
retVal += "#" + to_string(linkWithTemplate.size());
|
||||
for (int i = 0; i < linkWithTemplate.size(); ++i)
|
||||
retVal += "#" + to_string(linkWithTemplate[i]);
|
||||
|
||||
retVal += "#" + to_string(alignRuleWithTemplate.size());
|
||||
for (int i = 0; i < alignRuleWithTemplate.size(); ++i)
|
||||
retVal += "#" + to_string(alignRuleWithTemplate[i].first) + "#" + to_string(alignRuleWithTemplate[i].second);
|
||||
|
||||
retVal += "#" + to_string((long long)templateArray);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void TemplateLink::AddRule(const int dimNum, int dimTempl, const pair<int, int>& rule, Array* templateArray_)
|
||||
{
|
||||
linkWithTemplate[dimNum] = dimTempl;
|
||||
alignRuleWithTemplate[dimNum] = rule;
|
||||
templateArray = templateArray_;
|
||||
}
|
||||
|
||||
const vector<pair<int, int>>& Array::GetSizes()
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return sizes;
|
||||
else
|
||||
{
|
||||
if (orderedSizes.size() == 0)
|
||||
orderedSizes = applyNewOrderS(sizes, templateDimsOrder);
|
||||
return orderedSizes;
|
||||
}
|
||||
}
|
||||
|
||||
const vector<pair<pair<Expression*, pair<int, int>>, pair<Expression*, pair<int, int>>>>&
|
||||
Array::GetSizesExpr()
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return sizesExpr;
|
||||
else
|
||||
{
|
||||
if (orderedSizesExpr.size() == 0)
|
||||
orderedSizesExpr = applyNewOrderS(sizesExpr, templateDimsOrder);
|
||||
return orderedSizesExpr;
|
||||
}
|
||||
}
|
||||
|
||||
void printArrayInfo(const string& file, const map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays)
|
||||
{
|
||||
FILE* out = fopen(file.c_str(), "w");
|
||||
if (out == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
Array* currA = elem.second.first;
|
||||
ArrayAccessInfo* info = elem.second.second;
|
||||
|
||||
fprintf(out, "Array '%s' (full name '%s'):\n", currA->GetShortName().c_str(), currA->GetName().c_str());
|
||||
auto loc = currA->GetLocation();
|
||||
string locN = "";
|
||||
if (loc.first == l_COMMON)
|
||||
locN = "COMMON ";
|
||||
else if (loc.first == l_MODULE)
|
||||
locN = "MODULE ";
|
||||
else if (loc.first == l_PARAMETER)
|
||||
locN = "PARAMETER of ";
|
||||
else if (loc.first == l_LOCAL)
|
||||
locN = "LOCAL of ";
|
||||
else if (loc.first == l_LOCAL_SAVE)
|
||||
locN = "LOCAL (save) of ";
|
||||
else if (loc.first == l_STRUCT)
|
||||
locN = "STRUCT ";
|
||||
else
|
||||
locN = "UNKN ";
|
||||
locN += "'" + loc.second + "'";
|
||||
|
||||
fprintf(out, " type: %s\n", locN.c_str());
|
||||
for (auto& byFile : info->GetAllAccessInfo())
|
||||
{
|
||||
fprintf(out, " FOR FILE '%s':\n", convertFileName(byFile.first.c_str()).c_str());
|
||||
for (auto& byLine : byFile.second)
|
||||
for (auto& onLine : byLine.second)
|
||||
fprintf(out, " %s\n", onLine.PrintInfo().c_str());
|
||||
}
|
||||
fprintf(out, "=============== \n\n");
|
||||
}
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
void fixTypeOfArrayInfoWithCallGraph(map<tuple<int, string, string>, pair<Array*, ArrayAccessInfo*>>& declaredArrays,
|
||||
const map<string, FuncInfo*>& allFuncs)
|
||||
{
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
ArrayAccessInfo* info = elem.second.second;
|
||||
info->checkAndUpdate(allFuncs);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayAccessInfo::checkAndUpdate(const map<string, FuncInfo*>& allFuncs)
|
||||
{
|
||||
for (auto& byFile : accessPatterns)
|
||||
{
|
||||
for (auto& byLine : byFile.second)
|
||||
{
|
||||
for (auto& acc : byLine.second)
|
||||
{
|
||||
if (acc.underFunctionPar != -1)
|
||||
{
|
||||
auto it = allFuncs.find(acc.fName);
|
||||
if (it != allFuncs.end())
|
||||
{
|
||||
if (it->second->funcParams.isArgIn(acc.underFunctionPar) &&
|
||||
!it->second->funcParams.isArgOut(acc.underFunctionPar))
|
||||
{
|
||||
//switch to READ
|
||||
acc.type = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
812
src/Distribution/Array.h
Normal file
812
src/Distribution/Array.h
Normal file
@@ -0,0 +1,812 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include "DvmhDirectiveBase.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
class Symbol;
|
||||
class Expression;
|
||||
struct FuncInfo;
|
||||
|
||||
#define STRING std::string
|
||||
#define VECTOR std::vector
|
||||
#define PAIR std::pair
|
||||
#define MAP std::map
|
||||
#define SET std::set
|
||||
#define TO_STR std::to_string
|
||||
|
||||
#if __SPF
|
||||
extern int sharedMemoryParallelization;
|
||||
#endif
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
typedef enum distFlag : int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType;
|
||||
typedef enum arrayLocation : int { l_LOCAL = 0, l_COMMON, l_MODULE, l_PARAMETER, l_STRUCT, l_LOCAL_SAVE } arrayLocType;
|
||||
|
||||
class Array;
|
||||
|
||||
class TemplateLink
|
||||
{
|
||||
private:
|
||||
VECTOR<int> linkWithTemplate;
|
||||
VECTOR<PAIR<int, int>> alignRuleWithTemplate;
|
||||
Array *templateArray;
|
||||
|
||||
public:
|
||||
TemplateLink(const int dimSize)
|
||||
{
|
||||
linkWithTemplate.resize(dimSize);
|
||||
alignRuleWithTemplate.resize(dimSize);
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
linkWithTemplate[i] = -1;
|
||||
templateArray = NULL;
|
||||
}
|
||||
|
||||
TemplateLink(const TemplateLink ©)
|
||||
{
|
||||
linkWithTemplate = copy.linkWithTemplate;
|
||||
alignRuleWithTemplate = copy.alignRuleWithTemplate;
|
||||
templateArray = copy.templateArray;
|
||||
}
|
||||
|
||||
Array* GetTemplateArray() const { return templateArray; }
|
||||
VECTOR<PAIR<int, int>> GetAlignRules() const;
|
||||
VECTOR<int> GetLinks() const;
|
||||
void AddRule(const int dimNum, int value, const PAIR<int, int> &rule, Array *templateArray_);
|
||||
STRING toString() const;
|
||||
};
|
||||
|
||||
class Array
|
||||
{
|
||||
private:
|
||||
unsigned id;
|
||||
STRING name;
|
||||
STRING shortName;
|
||||
int dimSize;
|
||||
int typeSize; // size of one element of array
|
||||
// calculated sizes
|
||||
VECTOR<PAIR<int, int>> sizes;
|
||||
// original sizes + shifts
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> sizesExpr;
|
||||
|
||||
VECTOR<PAIR<int, int>> orderedSizes;
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> orderedSizesExpr;
|
||||
|
||||
// template info by region
|
||||
MAP<uint64_t, TemplateLink*> templateInfo;
|
||||
bool isTemplFlag;
|
||||
bool isLoopArrayFlag;
|
||||
distFlag isNonDistribute;
|
||||
Symbol *declSymbol;
|
||||
STRING uniqKey;
|
||||
|
||||
// PAIR<FILE, LINE>
|
||||
SET<PAIR<STRING, int>> declPlaces;
|
||||
MAP<PAIR<STRING, int>, Symbol*> declPlacesSymbol;
|
||||
//file-> map[incFile, line] -> symbol
|
||||
MAP<STRING, MAP<PAIR<STRING, int>, Symbol*>> declPlacesSymbolByFile;
|
||||
|
||||
//TYPE: 0 - local, 1 - common, 2 - module, 3 - function parameter
|
||||
// PAIR<TYPE, NAME>
|
||||
PAIR<arrayLocation, STRING> locationPos;
|
||||
VECTOR<VECTOR<PAIR<int, int>>> allShadowSpecs;
|
||||
|
||||
SET<STRING> containsInRegions;
|
||||
|
||||
// file -> lines
|
||||
MAP<STRING, SET<int>> usagePlaces;
|
||||
|
||||
VECTOR<bool> mappedDims;
|
||||
VECTOR<bool> depracateToDistribute;
|
||||
|
||||
bool ompThreadPrivate;
|
||||
bool privateInLoop;
|
||||
bool inEquivalence;
|
||||
private:
|
||||
TemplateLink* getTemlateInfo(const uint64_t regionId, bool withCheck = false)
|
||||
{
|
||||
auto it = templateInfo.find(regionId);
|
||||
TemplateLink *currLink = NULL;
|
||||
if (it == templateInfo.end())
|
||||
{
|
||||
#if __SPF
|
||||
if (withCheck && sharedMemoryParallelization != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#endif
|
||||
currLink = new TemplateLink(dimSize);
|
||||
templateInfo[regionId] = currLink;
|
||||
}
|
||||
else
|
||||
currLink = it->second;
|
||||
return currLink;
|
||||
}
|
||||
|
||||
void GenUniqKey()
|
||||
{
|
||||
uniqKey = shortName + locationPos.second + TO_STR(dimSize);
|
||||
for (auto &place : declPlaces)
|
||||
uniqKey += place.first + TO_STR(place.second);
|
||||
}
|
||||
|
||||
//clones of template for realignes
|
||||
MAP<VECTOR<dist>, STRING> templateClones;
|
||||
VECTOR<int> templateDimsOrder;
|
||||
|
||||
public:
|
||||
Array()
|
||||
{
|
||||
isTemplFlag = false;
|
||||
isLoopArrayFlag = false;
|
||||
isNonDistribute = NO_DISTR;
|
||||
typeSize = 0;
|
||||
uniqKey = "";
|
||||
dimSize = 0;
|
||||
id = -1;
|
||||
declSymbol = NULL;
|
||||
ompThreadPrivate = false;
|
||||
privateInLoop = false;
|
||||
inEquivalence = false;
|
||||
}
|
||||
|
||||
Array(const STRING &name, const STRING &shortName, const int dimSize, const unsigned id,
|
||||
const STRING &declFile, const int declLine, const PAIR<arrayLocation, STRING> &locationPos,
|
||||
Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence,
|
||||
const VECTOR<STRING> ®ions, const int typeSize, const distFlag flag = DISTR) :
|
||||
|
||||
name(name), dimSize(dimSize), id(id), shortName(shortName),
|
||||
isTemplFlag(false), isNonDistribute(flag), isLoopArrayFlag(false),
|
||||
locationPos(locationPos), declSymbol(declSymbol), typeSize(typeSize),
|
||||
ompThreadPrivate(inOmpThreadPriv), privateInLoop(privateInLoop), inEquivalence(inEquivalence)
|
||||
{
|
||||
declPlaces.insert(std::make_pair(declFile, declLine));
|
||||
sizes.resize(dimSize);
|
||||
sizesExpr.resize(dimSize);
|
||||
mappedDims.resize(dimSize);
|
||||
depracateToDistribute.resize(dimSize);
|
||||
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
sizes[z] = std::make_pair((int)INT_MAX, (int)INT_MIN);
|
||||
PAIR<int, int> initVal = std::make_pair(0, 0);
|
||||
sizesExpr[z] = std::make_pair(std::make_pair((Expression*)NULL, initVal), std::make_pair((Expression*)NULL, initVal));
|
||||
mappedDims[z] = false;
|
||||
depracateToDistribute[z] = false;
|
||||
}
|
||||
|
||||
GenUniqKey();
|
||||
for (auto ® : regions)
|
||||
containsInRegions.insert(reg);
|
||||
}
|
||||
|
||||
Array(const Array ©)
|
||||
{
|
||||
id = copy.id;
|
||||
name = copy.name;
|
||||
shortName = copy.shortName;
|
||||
dimSize = copy.dimSize;
|
||||
typeSize = copy.typeSize;
|
||||
|
||||
sizes = copy.sizes;
|
||||
sizesExpr = copy.sizesExpr;
|
||||
|
||||
isTemplFlag = copy.isTemplFlag;
|
||||
isNonDistribute = copy.isNonDistribute;
|
||||
isLoopArrayFlag = copy.isLoopArrayFlag;
|
||||
|
||||
declPlaces = copy.declPlaces;
|
||||
locationPos = copy.locationPos;
|
||||
|
||||
allShadowSpecs = copy.allShadowSpecs;
|
||||
|
||||
for (auto &elem : copy.templateInfo)
|
||||
templateInfo[elem.first] = new TemplateLink(*elem.second);
|
||||
|
||||
declSymbol = copy.declSymbol;
|
||||
uniqKey = copy.uniqKey;
|
||||
containsInRegions = copy.containsInRegions;
|
||||
mappedDims = copy.mappedDims;
|
||||
depracateToDistribute = copy.depracateToDistribute;
|
||||
ompThreadPrivate = copy.ompThreadPrivate;
|
||||
privateInLoop = copy.privateInLoop;
|
||||
inEquivalence = copy.inEquivalence;
|
||||
}
|
||||
|
||||
bool RemoveUnpammedDims()
|
||||
{
|
||||
bool needToRemove = false;
|
||||
int countToRem = 0;
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
if (!mappedDims[z] || depracateToDistribute[z])
|
||||
{
|
||||
needToRemove = true;
|
||||
countToRem++;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToRemove == false)
|
||||
return false;
|
||||
if (countToRem == dimSize)
|
||||
return true;
|
||||
|
||||
VECTOR<PAIR<int, int>> newSizes;
|
||||
VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>> newSizesExpr;
|
||||
VECTOR<bool> newMappedDims;
|
||||
VECTOR<bool> newDepr;
|
||||
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
{
|
||||
if (mappedDims[z] && !depracateToDistribute[z])
|
||||
{
|
||||
newSizes.push_back(sizes[z]);
|
||||
newSizesExpr.push_back(sizesExpr[z]);
|
||||
newMappedDims.push_back(mappedDims[z]);
|
||||
newDepr.push_back(depracateToDistribute[z]);
|
||||
}
|
||||
}
|
||||
|
||||
sizes = newSizes;
|
||||
sizesExpr = newSizesExpr;
|
||||
mappedDims = newMappedDims;
|
||||
depracateToDistribute = newDepr;
|
||||
dimSize = (int)sizes.size();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetDimSize() const { return dimSize; }
|
||||
const STRING GetName() const { return name; }
|
||||
const STRING GetShortName() const { return shortName; }
|
||||
const STRING GetNameInLocation(void* location) const;
|
||||
void* GetNameInLocationS(void* location) const;
|
||||
|
||||
unsigned GetId() const { return id; }
|
||||
void SetSizes(VECTOR<PAIR<int, int>> &_sizes, bool notCopyToExpr = false)
|
||||
{
|
||||
sizes = _sizes;
|
||||
if (!notCopyToExpr)
|
||||
{
|
||||
for (int i = 0; i < sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.second.first = sizes[i].first;
|
||||
sizesExpr[i].second.second.first = sizes[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
const VECTOR<PAIR<int, int>>& GetSizes();
|
||||
const VECTOR<PAIR<PAIR<Expression*, PAIR<int, int>>, PAIR<Expression*, PAIR<int, int>>>>& GetSizesExpr();
|
||||
void SetTemplateFlag(const bool templFlag) { isTemplFlag = templFlag; }
|
||||
bool IsTemplate() const { return isTemplFlag; }
|
||||
bool IsLoopArray() const { return isLoopArrayFlag; }
|
||||
bool IsArray() const { return !isTemplFlag && !isLoopArrayFlag; }
|
||||
void SetLoopArray(const bool flag) { isLoopArrayFlag = flag; }
|
||||
void SetSizesExpr(const VECTOR<PAIR<Expression*, Expression*>> &_sizesExpr)
|
||||
{
|
||||
for (int i = 0; i < _sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.first = _sizesExpr[i].first;
|
||||
sizesExpr[i].second.first = _sizesExpr[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
int AddLinkWithTemplate(const int dimNum, const int dimTempl, Array *templateArray_, const PAIR<int, int> &rule, const uint64_t regionId)
|
||||
{
|
||||
int err = 0;
|
||||
if (dimNum >= dimSize)
|
||||
err = -1;
|
||||
else
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, templateArray_ == NULL);
|
||||
currLink->AddRule(dimNum, dimTempl, rule, templateArray_);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
VECTOR<int> GetLinksWithTemplate(const uint64_t regionId)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, true);
|
||||
return currLink->GetLinks();
|
||||
}
|
||||
|
||||
VECTOR<PAIR<int, int>> GetAlignRulesWithTemplate(const uint64_t regionId)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, true);
|
||||
return currLink->GetAlignRules();
|
||||
}
|
||||
|
||||
bool HasTemplateInfo(const uint64_t regionId) const
|
||||
{
|
||||
auto it = templateInfo.find(regionId);
|
||||
return (it != templateInfo.end());
|
||||
}
|
||||
|
||||
void ChangeName(const STRING &newName)
|
||||
{
|
||||
auto pos = name.find(shortName);
|
||||
if (pos != STRING::npos)
|
||||
{
|
||||
name.erase(pos, shortName.size());
|
||||
shortName = newName;
|
||||
name += newName;
|
||||
}
|
||||
GenUniqKey();
|
||||
}
|
||||
|
||||
void ExtendDimSize(const int dim, const PAIR<int, int> &size)
|
||||
{
|
||||
/*if (size.first == size.second)
|
||||
return;*/
|
||||
|
||||
sizes[dim].first = std::min(sizes[dim].first, size.first);
|
||||
sizes[dim].second = std::max(sizes[dim].second, size.second);
|
||||
|
||||
PAIR<int, int> &left = sizesExpr[dim].first.second;
|
||||
PAIR<int, int> &right = sizesExpr[dim].second.second;
|
||||
|
||||
left.second = std::min(left.second, sizes[dim].first - left.first);
|
||||
right.second = std::max(right.second, sizes[dim].second - right.first);
|
||||
}
|
||||
void SetId(const unsigned newId) { id = newId; }
|
||||
|
||||
const SET<PAIR<STRING, int>>& GetDeclInfo() const { return declPlaces; }
|
||||
const MAP<PAIR<STRING, int>, Symbol*>& GetDeclInfoWithSymb() const { return declPlacesSymbol; }
|
||||
void AddDeclInfo(const PAIR<STRING, int> &declInfo, const SET<STRING>& allFilesInProj,
|
||||
const STRING& currFile, Symbol* symb = NULL)
|
||||
{
|
||||
declPlaces.insert(declInfo);
|
||||
if (symb)
|
||||
{
|
||||
declPlacesSymbol[declInfo] = symb;
|
||||
if (allFilesInProj.find(declInfo.first) == allFilesInProj.end()) // from include
|
||||
declPlacesSymbolByFile[currFile][declInfo] = symb;
|
||||
}
|
||||
GenUniqKey();
|
||||
}
|
||||
|
||||
//save request of shadow spec
|
||||
void ExtendShadowSpec(const VECTOR<PAIR<int, int>> &newSpec)
|
||||
{
|
||||
if (allShadowSpecs.size() == 0)
|
||||
allShadowSpecs.resize(dimSize);
|
||||
|
||||
const PAIR<int, int> zeroPair(0, 0);
|
||||
for (int i = 0; i < newSpec.size(); ++i)
|
||||
if (newSpec[i] != zeroPair)
|
||||
allShadowSpecs[i].push_back(newSpec[i]);
|
||||
}
|
||||
|
||||
//remove last requst of shadow spec
|
||||
void RemoveShadowSpec(const VECTOR<PAIR<int, int>> &delSpec)
|
||||
{
|
||||
int dimN = 0;
|
||||
for (auto &group : allShadowSpecs)
|
||||
{
|
||||
for (int i = 0; i < group.size(); ++i)
|
||||
{
|
||||
if (group[i] == delSpec[dimN])
|
||||
{
|
||||
group.erase(group.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++dimN;
|
||||
}
|
||||
}
|
||||
|
||||
//construct shadow spec from all requests
|
||||
const VECTOR<PAIR<int, int>> GetShadowSpec() const
|
||||
{
|
||||
VECTOR<PAIR<int, int>> shadowSpec;
|
||||
shadowSpec.resize(dimSize);
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
shadowSpec[i] = std::make_pair(0, 0);
|
||||
|
||||
int dimN = 0;
|
||||
for (auto &group : allShadowSpecs)
|
||||
{
|
||||
for (auto &elem : group)
|
||||
{
|
||||
shadowSpec[dimN].first = std::max(shadowSpec[dimN].first, elem.first);
|
||||
shadowSpec[dimN].second = std::max(shadowSpec[dimN].second, elem.second);
|
||||
}
|
||||
++dimN;
|
||||
}
|
||||
return shadowSpec;
|
||||
}
|
||||
|
||||
void ClearShadowSpecs() { allShadowSpecs.clear(); }
|
||||
|
||||
STRING toString()
|
||||
{
|
||||
STRING retVal = "";
|
||||
retVal += TO_STR(id);
|
||||
retVal += "#" + name;
|
||||
retVal += "#" + shortName;
|
||||
retVal += "#" + TO_STR(dimSize);
|
||||
retVal += "#" + TO_STR(typeSize);
|
||||
retVal += "#" + TO_STR(isNonDistribute);
|
||||
|
||||
retVal += "#" + TO_STR(locationPos.first);
|
||||
retVal += "#" + locationPos.second;
|
||||
|
||||
retVal += "#" + TO_STR(sizes.size());
|
||||
for (int i = 0; i < sizes.size(); ++i)
|
||||
retVal += "#" + TO_STR(sizes[i].first) + "#" + TO_STR(sizes[i].second);
|
||||
|
||||
retVal += "#" + TO_STR(depracateToDistribute.size());
|
||||
for (int i = 0; i < depracateToDistribute.size(); ++i)
|
||||
retVal += "#" + TO_STR((int)depracateToDistribute[i]);
|
||||
|
||||
retVal += "#" + TO_STR(mappedDims.size());
|
||||
for (int i = 0; i < mappedDims.size(); ++i)
|
||||
retVal += "#" + TO_STR((int)mappedDims[i]);
|
||||
|
||||
retVal += "#" + TO_STR(templateInfo.size());
|
||||
for (auto it = templateInfo.begin(); it != templateInfo.end(); ++it)
|
||||
retVal += "#" + TO_STR(it->first) + it->second->toString();
|
||||
|
||||
retVal += "#" + TO_STR((int)isTemplFlag);
|
||||
retVal += "|" + TO_STR((int)isLoopArrayFlag);
|
||||
retVal += "|" + TO_STR(declPlaces.size());
|
||||
|
||||
for (auto &place : declPlaces)
|
||||
retVal += "|" + place.first + "|" + TO_STR(place.second);
|
||||
|
||||
retVal += "|" + TO_STR(containsInRegions.size());
|
||||
for (auto ® : containsInRegions)
|
||||
retVal += "|" + reg;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
Array* GetTemplateArray(const uint64_t regionId, bool withCheck = true)
|
||||
{
|
||||
TemplateLink *currLink = getTemlateInfo(regionId, withCheck);
|
||||
return currLink->GetTemplateArray();
|
||||
}
|
||||
|
||||
void SetDistributeFlag(const distFlag isNonDistribute_) { isNonDistribute = isNonDistribute_; }
|
||||
bool IsNotDistribute() const { return (isNonDistribute == DISTR) ? false : true; }
|
||||
distFlag GetDistributeFlagVal() const { return isNonDistribute; }
|
||||
|
||||
void ChangeLocation(arrayLocation loc, const STRING &name)
|
||||
{
|
||||
locationPos = std::make_pair(loc, name);
|
||||
}
|
||||
|
||||
void SetLocation(arrayLocation loc, const STRING &name)
|
||||
{
|
||||
ChangeLocation(loc, name);
|
||||
GenUniqKey();
|
||||
}
|
||||
PAIR<arrayLocation, STRING> GetLocation() const { return locationPos; }
|
||||
|
||||
Symbol* GetDeclSymbol(const STRING& file, const PAIR<int, int>& range, const SET<STRING>& allFilesInProj) const
|
||||
{
|
||||
if (!IsArray() || locationPos.first != l_COMMON)
|
||||
return declSymbol;
|
||||
|
||||
for (auto& pos : declPlacesSymbol)
|
||||
{
|
||||
if (pos.first.first == file)
|
||||
{
|
||||
const int line = pos.first.second;
|
||||
if (range.first <= line && line <= range.second)
|
||||
return pos.second;
|
||||
} // may be in include?
|
||||
else if (allFilesInProj.find(pos.first.first) == allFilesInProj.end() && allFilesInProj.size())
|
||||
{
|
||||
auto it = declPlacesSymbolByFile.find(file);
|
||||
if (it != declPlacesSymbolByFile.end() && it->second.find(pos.first) != it->second.end())
|
||||
{
|
||||
auto s = it->second.find(pos.first);
|
||||
return s->second;
|
||||
}
|
||||
else
|
||||
#if __SPF
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#if __SPF
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Symbol* GetDeclSymbol() const { return declSymbol; }
|
||||
void SetDeclSymbol(Symbol *s) { declSymbol = s; }
|
||||
|
||||
const STRING& GetArrayUniqKey() const { return uniqKey; }
|
||||
|
||||
STRING GetIndepUniqName() const { return shortName + locationPos.second + TO_STR(dimSize); }
|
||||
|
||||
const SET<STRING>& GetRegionsName() const { return containsInRegions; }
|
||||
void SetRegionPlace(const STRING ®Name) { if (regName != "") containsInRegions.insert(regName); }
|
||||
|
||||
const MAP<STRING, SET<int>>& GetUsagePlaces() const { return usagePlaces; }
|
||||
const SET<int> GetUsagePlaces(const STRING& fileName, const PAIR<int, int>* filter = NULL) const
|
||||
{
|
||||
auto it = usagePlaces.find(fileName);
|
||||
if (it == usagePlaces.end())
|
||||
return SET<int>();
|
||||
if (!filter)
|
||||
return it->second;
|
||||
else
|
||||
{
|
||||
SET<int> ret;
|
||||
int first = filter->first;
|
||||
int last = filter->second;
|
||||
for (auto& elem : it->second)
|
||||
if (first <= elem && elem <= last)
|
||||
ret.insert(elem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void AddUsagePlace(const STRING &fileName, int lineNumber)
|
||||
{
|
||||
auto it = usagePlaces.find(fileName);
|
||||
if (it == usagePlaces.end())
|
||||
it = usagePlaces.insert(it, make_pair(fileName, SET<int>()));
|
||||
it->second.insert(lineNumber);
|
||||
}
|
||||
|
||||
void SetMappedDim(const int dim)
|
||||
{
|
||||
if (dim >= dimSize)
|
||||
return;
|
||||
mappedDims[dim] = true;
|
||||
}
|
||||
|
||||
bool IsDimMapped(const int dim) const
|
||||
{
|
||||
if (dim >= dimSize)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return mappedDims[dim];
|
||||
else
|
||||
return mappedDims[templateDimsOrder[dim]];
|
||||
}
|
||||
}
|
||||
|
||||
void DeprecateDimension(const int dim, bool value = true)
|
||||
{
|
||||
if (dim >= dimSize)
|
||||
return;
|
||||
depracateToDistribute[dim] = value;
|
||||
}
|
||||
|
||||
void DeprecateAllDims()
|
||||
{
|
||||
for (int dim = 0; dim < dimSize; ++dim)
|
||||
depracateToDistribute[dim] = true;
|
||||
}
|
||||
|
||||
bool IsDimDepracated(const int dim) const
|
||||
{
|
||||
if (dim >= dimSize)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
if (templateDimsOrder.size() == 0)
|
||||
return depracateToDistribute[dim];
|
||||
else
|
||||
return depracateToDistribute[templateDimsOrder[dim]];
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAllDeprecated() const
|
||||
{
|
||||
bool ret = true;
|
||||
for (int z = 0; z < dimSize; ++z)
|
||||
ret = ret && depracateToDistribute[z];
|
||||
return ret;
|
||||
}
|
||||
|
||||
const VECTOR<bool>& GetDeprecetedDims() const { return depracateToDistribute; }
|
||||
|
||||
int GetTypeSize() const { return typeSize; }
|
||||
|
||||
STRING AddTemplateClone(const VECTOR<dist> &newDist)
|
||||
{
|
||||
auto it = templateClones.find(newDist);
|
||||
if (it == templateClones.end())
|
||||
it = templateClones.insert(it, std::make_pair(newDist, shortName + STRING("_r") + TO_STR(templateClones.size())));
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void ClearTemplateClones()
|
||||
{
|
||||
templateClones.clear();
|
||||
templateDimsOrder.clear();
|
||||
orderedSizes.clear();
|
||||
orderedSizesExpr.clear();
|
||||
}
|
||||
|
||||
const MAP<VECTOR<dist>, STRING>& GetAllClones() const { return templateClones; }
|
||||
|
||||
void AddNewTemplateDimsOrder(const VECTOR<int> &newOrder) { templateDimsOrder = newOrder; }
|
||||
|
||||
VECTOR<int> GetNewTemplateDimsOrder() const { return templateDimsOrder; }
|
||||
|
||||
void SetDimSizesToMaxMin(bool notCopyToExpr = false)
|
||||
{
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
sizes[i] = std::make_pair((int)INT_MAX, (int)INT_MIN);
|
||||
|
||||
if (!notCopyToExpr)
|
||||
{
|
||||
for (int i = 0; i < sizesExpr.size(); ++i)
|
||||
{
|
||||
sizesExpr[i].first.second.first = sizes[i].first;
|
||||
sizesExpr[i].second.second.first = sizes[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOmpThreadPrivate() const { return ompThreadPrivate; }
|
||||
bool IsSpfPrivate() const { return ((isNonDistribute == SPF_PRIV) || (isNonDistribute == IO_PRIV)); }
|
||||
|
||||
bool IsInEquvalence() const { return inEquivalence; }
|
||||
void SetEquvalence(bool value) { inEquivalence = value; }
|
||||
|
||||
bool IsPrivateInLoop() const { return privateInLoop; }
|
||||
void SetPrivateInLoopStatus(bool value) { privateInLoop = value; }
|
||||
|
||||
bool IsModuleSymbol() const { return locationPos.first == l_MODULE; }
|
||||
|
||||
~Array()
|
||||
{
|
||||
for (auto &templ : templateInfo)
|
||||
delete templ.second;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayComparator
|
||||
{
|
||||
bool operator()(const Array* left, const Array* right) const
|
||||
{
|
||||
return (left->GetArrayUniqKey() > right->GetArrayUniqKey());
|
||||
}
|
||||
};
|
||||
|
||||
struct UnaryAccess
|
||||
{
|
||||
UnaryAccess()
|
||||
{
|
||||
line = -1;
|
||||
type = -1;
|
||||
underFunctionPar = -1;
|
||||
fName = "";
|
||||
count = 0;
|
||||
}
|
||||
|
||||
UnaryAccess(const PAIR<int, char>& info)
|
||||
{
|
||||
line = info.first;
|
||||
type = info.second;
|
||||
underFunctionPar = -1;
|
||||
fName = "";
|
||||
count = 1;
|
||||
}
|
||||
|
||||
UnaryAccess(const PAIR<int, char>& info, const STRING &f, const int parN)
|
||||
{
|
||||
line = info.first;
|
||||
type = info.second;
|
||||
underFunctionPar = parN;
|
||||
fName = f;
|
||||
count = 1;
|
||||
}
|
||||
|
||||
STRING PrintInfo() const
|
||||
{
|
||||
STRING out = "#" + std::to_string(count) + " of ";
|
||||
if (type == 0)
|
||||
out += "READ ";
|
||||
else if(type == 1)
|
||||
out += "WRITE ";
|
||||
else
|
||||
out += "UNKN ";
|
||||
out += "on line " + std::to_string(line);
|
||||
if (underFunctionPar != -1)
|
||||
out += " in '#" + std::to_string(underFunctionPar + 1) + "' par of function call '" + fName + "'";
|
||||
return out;
|
||||
}
|
||||
|
||||
bool operator==(const UnaryAccess &left) const
|
||||
{
|
||||
return (line == left.line && type == left.type &&
|
||||
underFunctionPar == left.underFunctionPar && fName == left.fName);
|
||||
}
|
||||
|
||||
bool operator!=(const UnaryAccess& left) const
|
||||
{
|
||||
return !(*this == left);
|
||||
}
|
||||
|
||||
int line;
|
||||
int type; // R/W -> 0, 1
|
||||
int underFunctionPar;
|
||||
STRING fName;
|
||||
int count;
|
||||
};
|
||||
|
||||
class ArrayAccessInfo
|
||||
{
|
||||
private:
|
||||
MAP<STRING, MAP<int, VECTOR<UnaryAccess>>> accessPatterns; // file -> MAP<LINE, info>
|
||||
public:
|
||||
void AddAccessInfo(const STRING& file, const PAIR<int, char> &info, const STRING fName = "", int underParN = -1)
|
||||
{
|
||||
auto it = accessPatterns.find(file);
|
||||
if (it == accessPatterns.end())
|
||||
it = accessPatterns.insert(it, std::make_pair(file, MAP<int, VECTOR<UnaryAccess>>()));
|
||||
|
||||
bool found = false;
|
||||
UnaryAccess toAdd;
|
||||
if (underParN == -1)
|
||||
toAdd = UnaryAccess(info);
|
||||
else
|
||||
toAdd = UnaryAccess(info, fName, underParN);
|
||||
|
||||
auto itMap = it->second.find(info.first);
|
||||
if (itMap == it->second.end())
|
||||
it->second[info.first].push_back(toAdd);
|
||||
else
|
||||
{
|
||||
for (int z = 0; z < itMap->second.size(); ++z)
|
||||
{
|
||||
if (itMap->second[z] == toAdd)
|
||||
{
|
||||
found = true;
|
||||
itMap->second[z].count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == false)
|
||||
{
|
||||
if (underParN == -1)
|
||||
itMap->second.push_back(toAdd);
|
||||
else
|
||||
itMap->second.push_back(toAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkAndUpdate(const MAP<STRING, FuncInfo*>& allFuncs);
|
||||
const MAP<STRING, MAP<int, VECTOR<UnaryAccess>>>& GetAllAccessInfo() const { return accessPatterns; }
|
||||
const MAP<int, VECTOR<UnaryAccess>>* GetAccessInfoByFile(const STRING &file) const
|
||||
{
|
||||
auto it = accessPatterns.find(file);
|
||||
if (it == accessPatterns.end())
|
||||
return NULL;
|
||||
else
|
||||
return &(it->second);
|
||||
}
|
||||
};
|
||||
|
||||
void printArrayInfo(const STRING &file, const MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>> &declaredArrays);
|
||||
void fixTypeOfArrayInfoWithCallGraph(MAP<std::tuple<int, STRING, STRING>, PAIR<Array*, ArrayAccessInfo*>>& declaredArrays, const MAP<STRING, FuncInfo*>& allFuncs);
|
||||
}
|
||||
#undef VECTOR
|
||||
#undef STRING
|
||||
#undef PAIR
|
||||
#undef MAP
|
||||
#undef SET
|
||||
#undef TO_STR
|
||||
766
src/Distribution/ArrayAnalysis.cpp
Normal file
766
src/Distribution/ArrayAnalysis.cpp
Normal file
@@ -0,0 +1,766 @@
|
||||
#include "Array.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../DirectiveProcessing/directive_parser.h"
|
||||
#include "../DirectiveProcessing/directive_omp_parser.h"
|
||||
#include "../LoopAnalyzer/loop_analyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern int ignoreIO;
|
||||
extern map<DIST::Array*, std::tuple<int, string, string>> tableOfUniqNamesByArray;
|
||||
static set<tuple<int, string, string>> checkedArraysForWrongLocation;
|
||||
|
||||
static bool findOmpThreadPrivDecl(SgStatement* st, map<SgStatement*, set<string>>& ompThreadPrivate, SgSymbol* toFind)
|
||||
{
|
||||
|
||||
auto it = ompThreadPrivate.find(st);
|
||||
if (it == ompThreadPrivate.end())
|
||||
{
|
||||
it = ompThreadPrivate.insert(it, make_pair(st, set<string>()));
|
||||
|
||||
SgStatement* lastN = st->lastNodeOfStmt();
|
||||
set<string> dummy;
|
||||
do
|
||||
{
|
||||
st = st->lexNext();
|
||||
|
||||
auto res = parseOmpInStatement(st, dummy);
|
||||
for (auto& dir : res)
|
||||
for (auto& var : dir.threadPrivVars)
|
||||
it->second.insert(var);
|
||||
} while (st != lastN && !isSgExecutableStatement(st) && st->variant() != CONTAINS_STMT);
|
||||
}
|
||||
|
||||
if (it->second.find(toFind->identifier()) != it->second.end())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasAssingOpInDecl(SgSymbol* symb)
|
||||
{
|
||||
vector<SgStatement*> allDecls;
|
||||
SgStatement* decl = declaratedInStmt(symb, &allDecls);
|
||||
|
||||
for (auto& elem : allDecls)
|
||||
{
|
||||
if (elem->variant() == VAR_DECL_90)
|
||||
{
|
||||
SgExpression* list = elem->expr(0);
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs()->variant() == ASSGN_OP)
|
||||
if (list->lhs()->lhs()->symbol() && OriginalSymbol(list->lhs()->lhs()->symbol()) == symb)
|
||||
return true;
|
||||
list = list->rhs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static string getNameWithScope(SgStatement* scope, const string& currFunctionName)
|
||||
{
|
||||
if (scope && isSgProgHedrStmt(scope) && scope->symbol()->identifier() != currFunctionName)
|
||||
return scope->symbol()->identifier();
|
||||
else
|
||||
return currFunctionName;
|
||||
}
|
||||
|
||||
struct findInfo
|
||||
{
|
||||
findInfo(const string fName, SgExpression* ex, int parN, bool isWrite) :
|
||||
fName(fName), ex(ex), parN(parN), isWrite(isWrite)
|
||||
{ }
|
||||
|
||||
SgExpression* ex;
|
||||
string fName;
|
||||
int parN;
|
||||
bool isWrite;
|
||||
};
|
||||
|
||||
static void findArrayRefs (SgExpression* ex, SgStatement* st, string fName, int parN, bool isWrite,
|
||||
const map<string, vector<SgExpression*>>& commonBlocks,
|
||||
map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
|
||||
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt,
|
||||
const set<string>& privates, const set<string>& deprecatedByIO,
|
||||
bool isExecutable, const string& currFunctionName,
|
||||
const vector<string>& inRegion,
|
||||
const set<string>& funcParNames,
|
||||
map<SgStatement*, set<string>>& ompThreadPrivate,
|
||||
const map<string, int>& distrStateFromGUI,
|
||||
const bool saveAllLocals,
|
||||
map<string, vector<Messages>>& currMessages,
|
||||
int& errorCount)
|
||||
{
|
||||
const string globalFile = current_file->filename();
|
||||
const set<string> filesInProj = getAllFilesInProject();
|
||||
|
||||
if (ex == NULL)
|
||||
return;
|
||||
stack<findInfo> queue;
|
||||
queue.push(findInfo(fName, ex, parN, isWrite));
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
const findInfo& curQ = queue.top();
|
||||
ex = curQ.ex;
|
||||
fName = curQ.fName;
|
||||
parN = curQ.parN;
|
||||
isWrite = curQ.isWrite;
|
||||
|
||||
queue.pop();
|
||||
|
||||
if (isArrayRef(ex))
|
||||
{
|
||||
SgSymbol* symb = OriginalSymbol(ex->symbol());
|
||||
const bool inDataStat = (symb->attributes() & DATA_BIT) != 0 || ((ex->symbol())->attributes() & DATA_BIT);
|
||||
checkNull(symb->type(), convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const int typeSize = getSizeOfType(symb->type()->baseType());
|
||||
if (typeSize == 0)
|
||||
{
|
||||
//__spf_print(1, "Wrong type size for array %s\n", symb->identifier());
|
||||
//printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
SgStatement* decl = declaratedInStmt(symb);
|
||||
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
|
||||
{
|
||||
const string tmp(decl->unparse());
|
||||
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
|
||||
{
|
||||
auto sTemp = symb->identifier();
|
||||
tuple<int, string, string> uniqKey;
|
||||
bool found = false;
|
||||
for (auto& elem : declaredArrays)
|
||||
{
|
||||
if (elem.second.first->GetShortName() == sTemp)
|
||||
{
|
||||
uniqKey = elem.first;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
auto itDecl = declaratedArraysSt.find(decl);
|
||||
if (itDecl == declaratedArraysSt.end())
|
||||
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
|
||||
itDecl->second.insert(uniqKey);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto uniqKey = getUniqName(commonBlocks, decl, symb);
|
||||
|
||||
SgStatement* scope = symb->scope();
|
||||
pair<DIST::arrayLocType, string> arrayLocation;
|
||||
|
||||
string typePrefix = "";
|
||||
while (scope && scope->variant() == STRUCT_DECL)
|
||||
{
|
||||
if (typePrefix == "")
|
||||
typePrefix = scope->symbol()->identifier();
|
||||
else
|
||||
typePrefix += scope->symbol()->identifier() + string("::");
|
||||
scope = scope->controlParent();
|
||||
}
|
||||
|
||||
if ((ex->symbol() && symb != ex->symbol()) || (scope && scope->variant() == MODULE_STMT))
|
||||
{
|
||||
if (scope)
|
||||
{
|
||||
string modName = scope->symbol()->identifier();
|
||||
arrayLocation = make_pair(DIST::l_MODULE, (typePrefix == "") ? modName : modName + "::" + typePrefix);
|
||||
}
|
||||
else //TODO: find module name with another way
|
||||
arrayLocation = make_pair(DIST::l_MODULE, "UNREC_MODULE_NAME");
|
||||
}
|
||||
else if (get<1>(uniqKey).find("common_") != string::npos)
|
||||
arrayLocation = make_pair(DIST::l_COMMON, get<1>(uniqKey).substr(strlen("common_")));
|
||||
else if (funcParNames.find(symb->identifier()) != funcParNames.end())
|
||||
arrayLocation = make_pair(DIST::l_PARAMETER, getNameWithScope(scope, currFunctionName));
|
||||
else
|
||||
{
|
||||
if (saveAllLocals || ((symb->attributes() & SAVE_BIT) != 0) || hasAssingOpInDecl(symb))
|
||||
arrayLocation = make_pair(DIST::l_LOCAL_SAVE, getNameWithScope(scope, currFunctionName));
|
||||
else
|
||||
arrayLocation = make_pair(DIST::l_LOCAL, getNameWithScope(scope, currFunctionName));
|
||||
}
|
||||
|
||||
auto itNew = declaredArrays.find(uniqKey);
|
||||
if (itNew == declaredArrays.end())
|
||||
{
|
||||
DIST::Array* arrayToAdd =
|
||||
new DIST::Array(getShortName(uniqKey), symb->identifier(), ((SgArrayType*)(symb->type()))->dimension(),
|
||||
getUniqArrayId(), decl->fileName(), decl->lineNumber(), arrayLocation, new Symbol(symb),
|
||||
findOmpThreadPrivDecl(scope, ompThreadPrivate, symb), false, false,
|
||||
inRegion, typeSize, sharedMemoryParallelization ? DIST::NO_DISTR : DIST::DISTR);
|
||||
|
||||
itNew = declaredArrays.insert(itNew, make_pair(uniqKey, make_pair(arrayToAdd, new DIST::ArrayAccessInfo())));
|
||||
|
||||
vector<pair<int, int>> sizes;
|
||||
map<DIST::Array*, set<DIST::Array*>> arrayLinksByFuncCallsNotReady;
|
||||
map<string, vector<FuncInfo*>> allFuncInfoNoReady;
|
||||
auto sizesExpr = getArraySizes(sizes, symb, decl, arrayLinksByFuncCallsNotReady, allFuncInfoNoReady);
|
||||
arrayToAdd->SetSizes(sizes);
|
||||
arrayToAdd->SetSizesExpr(sizesExpr);
|
||||
tableOfUniqNamesByArray[arrayToAdd] = uniqKey;
|
||||
}
|
||||
else // check the same location from include!
|
||||
{
|
||||
auto prevLocation = itNew->second.first->GetLocation();
|
||||
if (prevLocation != arrayLocation)
|
||||
{
|
||||
if (checkedArraysForWrongLocation.find(uniqKey) == checkedArraysForWrongLocation.end())
|
||||
{
|
||||
checkedArraysForWrongLocation.insert(uniqKey);
|
||||
__spf_print(1, "can not change declaration area of array '%s' on line %d\n", symb->identifier(), st->lineNumber());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' has declaration area conflict, it might be worth applying the Include inlining pass", to_wstring(symb->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R184, to_wstring(symb->identifier()).c_str());
|
||||
|
||||
currMessages[st->fileName()].push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 1061));
|
||||
}
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((symb->attributes() & EQUIVALENCE_BIT) != 0)
|
||||
itNew->second.first->SetEquvalence(true);
|
||||
|
||||
for (auto& reg : inRegion)
|
||||
itNew->second.first->SetRegionPlace(reg);
|
||||
|
||||
const auto oldVal = itNew->second.first->GetDistributeFlagVal();
|
||||
bool isarrayInModule = (itNew->second.first->GetLocation().first == DIST::l_MODULE);
|
||||
|
||||
if (oldVal == DIST::DISTR || oldVal == DIST::NO_DISTR)
|
||||
{
|
||||
if (itNew->second.first->IsOmpThreadPrivate())
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
else if (privates.find(symb->identifier()) != privates.end() || isarrayInModule)
|
||||
{
|
||||
//check in module
|
||||
if (itNew->second.first->GetLocation().first == DIST::l_MODULE)
|
||||
{
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(decl, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
{
|
||||
set<string> privatesS;
|
||||
fillPrivatesFromComment(new Statement(data), privatesS);
|
||||
if (privatesS.find(symb->identifier()) != privatesS.end())
|
||||
{
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = decl->lexPrev();
|
||||
checkNull(prev, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
set<string> privatesS;
|
||||
fillPrivatesFromComment(new Statement(prev), privatesS);
|
||||
if (privatesS.find(symb->identifier()) != privatesS.end())
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
}
|
||||
else
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
}
|
||||
else if (deprecatedByIO.find(symb->identifier()) != deprecatedByIO.end())
|
||||
itNew->second.first->SetDistributeFlag(DIST::IO_PRIV);
|
||||
else if (isSgConstantSymb(symb) || inDataStat)
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
else
|
||||
{
|
||||
auto it = distrStateFromGUI.find(itNew->second.first->GetIndepUniqName());
|
||||
if (it != distrStateFromGUI.end())
|
||||
{
|
||||
if (it->second != oldVal)
|
||||
{
|
||||
itNew->second.first->SetDistributeFlag((DIST::distFlag)it->second);
|
||||
__spf_print(1, "change flag for array from cache '%s': %d -> %d\n", it->first.c_str(), oldVal, it->second);
|
||||
}
|
||||
}
|
||||
else
|
||||
itNew->second.first->SetDistributeFlag(DIST::DISTR);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeSize == 0) // unknown
|
||||
itNew->second.first->SetDistributeFlag(DIST::SPF_PRIV);
|
||||
|
||||
|
||||
if (!isExecutable)
|
||||
itNew->second.first->AddDeclInfo(make_pair(st->fileName(), st->lineNumber()), filesInProj, globalFile, new Symbol(symb));
|
||||
|
||||
if (isExecutable)
|
||||
{
|
||||
if (st->variant() != ALLOCATE_STMT && st->variant() != DEALLOCATE_STMT)
|
||||
{
|
||||
itNew->second.second->AddAccessInfo(st->fileName(), make_pair(st->lineNumber(), isWrite ? 1 : 0), fName, parN);
|
||||
itNew->second.first->AddUsagePlace(st->fileName(), st->lineNumber());
|
||||
}
|
||||
}
|
||||
|
||||
auto itDecl = declaratedArraysSt.find(decl);
|
||||
if (itDecl == declaratedArraysSt.end())
|
||||
itDecl = declaratedArraysSt.insert(itDecl, make_pair(decl, set<tuple<int, string, string>>()));
|
||||
itDecl->second.insert(uniqKey);
|
||||
|
||||
if (decl->variant() == DVM_VAR_DECL || decl->variant() == HPF_TEMPLATE_STAT)
|
||||
{
|
||||
const string tmp(decl->unparse());
|
||||
if (tmp.find("!DVM$ TEMPLATE") != string::npos)
|
||||
{
|
||||
itNew->second.first->SetTemplateFlag(true);
|
||||
//TODO: analyze align mapping
|
||||
for (int z = 0; z < itNew->second.first->GetDimSize(); ++z)
|
||||
itNew->second.first->SetMappedDim(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ex->variant() == FUNC_CALL)
|
||||
{
|
||||
SgFunctionCallExp* funcExp = (SgFunctionCallExp*)ex;
|
||||
const string fName = funcExp->funName()->identifier();
|
||||
bool intr = (isIntrinsicFunctionName(fName.c_str()) == 1);
|
||||
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
|
||||
{
|
||||
//assume all arguments of function as OUT, except for inctrinsics
|
||||
bool isWriteN = intr ? false : true;
|
||||
//need to correct W/R usage with GraphCall map later
|
||||
findArrayRefs(funcExp->arg(z), st, fName, z, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isWriteN = false;
|
||||
if (ex->lhs())
|
||||
queue.push(findInfo("", ex->lhs(), -1, isWriteN));
|
||||
if (ex->rhs())
|
||||
queue.push(findInfo("", ex->rhs(), -1, isWriteN));
|
||||
//findArrayRefs(ex->lhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
//findArrayRefs(ex->rhs(), st, "", -1, isWriteN, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO, isExecutable, currFunctionName, inRegion, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals, currMessages, errorCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void findArrayRefInIO(SgExpression* ex, set<string>& deprecatedByIO, SgStatement* st, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == ARRAY_REF)
|
||||
{
|
||||
auto symb = ex->symbol();
|
||||
if (symb->type())
|
||||
{
|
||||
if (symb->type()->variant() == T_ARRAY)
|
||||
{
|
||||
auto found = deprecatedByIO.find(OriginalSymbol(symb)->identifier());
|
||||
if (found == deprecatedByIO.end())
|
||||
{
|
||||
deprecatedByIO.insert(found, OriginalSymbol(symb)->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of DVM's I/O constraints", to_wstring(symb->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R68, to_wstring(symb->identifier()).c_str());
|
||||
|
||||
currMessages[st->fileName()].push_back(Messages(WARR, st->lineNumber(), messageR, messageE, 1037));
|
||||
|
||||
__spf_print(1, "Array '%s' at line %d can not be distributed because of DVM's I/O constraints\n", symb->identifier(), st->lineNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findArrayRefInIO(ex->lhs(), deprecatedByIO, st, currMessages);
|
||||
findArrayRefInIO(ex->rhs(), deprecatedByIO, st, currMessages);
|
||||
}
|
||||
}
|
||||
|
||||
static void findReshape(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* exL = st->expr(0);
|
||||
SgExpression* exR = st->expr(1);
|
||||
|
||||
if (exR->variant() == FUNC_CALL && exL->variant() == ARRAY_REF)
|
||||
{
|
||||
if (exR->symbol()->identifier() == string("reshape"))
|
||||
{
|
||||
if (privates.find(exL->symbol()->identifier()) == privates.end())
|
||||
{
|
||||
privates.insert(exL->symbol()->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of RESHAPE", to_wstring(exL->symbol()->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R90, to_wstring(exL->symbol()->identifier()).c_str());
|
||||
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void findConstructorRef(SgStatement* st, set<string>& privates, map<string, vector<Messages>>& currMessages)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* exL = st->expr(0);
|
||||
SgExpression* exR = st->expr(1);
|
||||
|
||||
if (exR->variant() == CONSTRUCTOR_REF && exL->variant() == ARRAY_REF)
|
||||
{
|
||||
if (privates.find(exL->symbol()->identifier()) == privates.end())
|
||||
{
|
||||
privates.insert(exL->symbol()->identifier());
|
||||
|
||||
wstring messageE, messageR;
|
||||
__spf_printToLongBuf(messageE, L"Array '%s' can not be distributed because of initializer list", to_wstring(exL->symbol()->identifier()).c_str());
|
||||
__spf_printToLongBuf(messageR, R164, to_wstring(exL->symbol()->identifier()).c_str());
|
||||
currMessages[st->fileName()].push_back(Messages(NOTE, st->lineNumber(), messageR, messageE, 1047));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void addPrivates(SgStatement* st, set<string>& privates, map<string, set<Symbol*>>& reductions,
|
||||
map<string, set<tuple<Symbol*, Symbol*, int>>>& reductionsLoc)
|
||||
{
|
||||
//after SPF preprocessing
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
{
|
||||
set<Symbol*> privatesS;
|
||||
fillPrivatesFromComment(new Statement(data), privatesS);
|
||||
fillReductionsFromComment(new Statement(data), reductions);
|
||||
fillReductionsFromComment(new Statement(data), reductionsLoc);
|
||||
|
||||
for (auto& elem : privatesS)
|
||||
privates.insert(elem->GetOriginal()->identifier());
|
||||
}
|
||||
|
||||
//before SPF preprocessing
|
||||
if (st->variant() == SPF_ANALYSIS_DIR)
|
||||
{
|
||||
set<Symbol*> privatesS;
|
||||
fillPrivatesFromComment(new Statement(st), privatesS);
|
||||
fillReductionsFromComment(new Statement(st), reductions);
|
||||
fillReductionsFromComment(new Statement(st), reductionsLoc);
|
||||
|
||||
for (auto& elem : privatesS)
|
||||
privates.insert(elem->GetOriginal()->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
int getAllDeclaredArrays(SgFile* file, map<tuple<int, string, string>, pair<DIST::Array*, DIST::ArrayAccessInfo*>>& declaredArrays,
|
||||
map<SgStatement*, set<tuple<int, string, string>>>& declaratedArraysSt, map<string, vector<Messages>>& currMessages,
|
||||
const vector<ParallelRegion*>& regions, const map<string, int>& distrStateFromGUI)
|
||||
{
|
||||
int countErrors = 0;
|
||||
|
||||
vector<SgStatement*> modules;
|
||||
findModulesInFile(file, modules);
|
||||
|
||||
map<string, set<string>> privatesByModule;
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
const string modName = mod->symbol()->identifier();
|
||||
privatesByModule[modName] = set<string>();
|
||||
auto it = privatesByModule.find(modName);
|
||||
|
||||
for (SgStatement* iter = mod; iter != mod->lastNodeOfStmt(); iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
//after SPF preprocessing
|
||||
for (auto& data : getAttributes<SgStatement*, SgStatement*>(iter, set<int>{ SPF_ANALYSIS_DIR }))
|
||||
fillPrivatesFromComment(new Statement(data), it->second);
|
||||
|
||||
//before SPF preprocessing
|
||||
if (iter->variant() == SPF_ANALYSIS_DIR)
|
||||
fillPrivatesFromComment(new Statement(iter), it->second);
|
||||
}
|
||||
}
|
||||
|
||||
map<SgStatement*, set<string>> ompThreadPrivate;
|
||||
|
||||
for (int i = 0; i < file->numberOfFunctions(); ++i)
|
||||
{
|
||||
bool saveAllLocals = false;
|
||||
|
||||
SgStatement* st = file->functions(i);
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
const string currFunctionName = st->symbol()->identifier();
|
||||
|
||||
getCommonBlocksRef(commonBlocks, st, lastNode);
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
map<string, set<Symbol*>> reductions;
|
||||
map<string, set<tuple<Symbol*, Symbol*, int>>> reductionsLoc;
|
||||
set<string> funcParNames;
|
||||
|
||||
if (st->variant() != PROG_HEDR)
|
||||
{
|
||||
SgProcHedrStmt* func = (SgProcHedrStmt*)st;
|
||||
for (int z = 0; z < func->numberOfParameters(); ++z)
|
||||
funcParNames.insert(func->parameter(z)->identifier());
|
||||
|
||||
if (func->nameWithContains() != func->name().identifier()) // added contains args
|
||||
{
|
||||
SgProcHedrStmt* cp = (SgProcHedrStmt*)func->controlParent();
|
||||
checkNull(cp, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int z = 0; z < cp->numberOfParameters(); ++z)
|
||||
funcParNames.insert(cp->parameter(z)->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
addPrivates(iter, privates, reductions, reductionsLoc);
|
||||
|
||||
if (iter->variant() == USE_STMT)
|
||||
fillFromModule(iter->symbol(), privatesByModule, privates);
|
||||
|
||||
if (iter->variant() == SAVE_DECL)
|
||||
if (!iter->expr(0) && !iter->expr(1) && !iter->expr(2))
|
||||
saveAllLocals = true;
|
||||
}
|
||||
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
findReshape(iter, privates, currMessages);
|
||||
findConstructorRef(iter, privates, currMessages);
|
||||
}
|
||||
|
||||
SgStatement* tmpModFind = st;
|
||||
while (tmpModFind->variant() != GLOBAL)
|
||||
{
|
||||
tmpModFind = tmpModFind->controlParent();
|
||||
if (tmpModFind->variant() == MODULE_STMT)
|
||||
fillFromModule(tmpModFind->symbol(), privatesByModule, privates);
|
||||
}
|
||||
|
||||
SgStatement* currF = st;
|
||||
SgStatement* contains = isSgProgHedrStmt(currF->controlParent());
|
||||
if (contains)
|
||||
{
|
||||
for (SgStatement* loc = contains; loc; loc = loc->lexNext())
|
||||
{
|
||||
if (isSgExecutableStatement(loc))
|
||||
break;
|
||||
if (loc->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (loc->variant() == USE_STMT)
|
||||
fillFromModule(loc->symbol(), privatesByModule, privates);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& elem : reductions)
|
||||
for (auto& setElem : elem.second)
|
||||
privates.insert(setElem->identifier());
|
||||
|
||||
for (auto& elem : reductionsLoc)
|
||||
{
|
||||
for (auto& setElem : elem.second)
|
||||
{
|
||||
privates.insert(get<0>(setElem)->identifier());
|
||||
privates.insert(get<1>(setElem)->identifier());
|
||||
}
|
||||
}
|
||||
|
||||
//analyze IO operations
|
||||
if (!ignoreIO)
|
||||
{
|
||||
for (SgStatement* iter = st; iter != lastNode; iter = iter->lexNext())
|
||||
{
|
||||
if (iter->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
SgInputOutputStmt* stIO = isSgInputOutputStmt(iter);
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, iter->fileName(), iter->lineNumber());
|
||||
if (stIO && currRegs.size()) // deprecate to distribute arrays only in regions
|
||||
{
|
||||
int countOfItems = 0;
|
||||
for (SgExpression* items = stIO->itemList(); items; items = items->rhs(), ++countOfItems);
|
||||
|
||||
//TODO: need to add more checkers!
|
||||
if (countOfItems > 1)
|
||||
{
|
||||
for (SgExpression* items = stIO->itemList(); items; items = items->rhs())
|
||||
findArrayRefInIO(items->lhs(), deprecatedByIO, stIO, currMessages);
|
||||
}
|
||||
else if (countOfItems == 1)
|
||||
{
|
||||
auto list = stIO->specList();
|
||||
bool ok = true;
|
||||
//exclude FMT='format'
|
||||
while (list)
|
||||
{
|
||||
if (list->lhs() && list->lhs()->variant() == SPEC_PAIR)
|
||||
{
|
||||
auto ex = list->lhs();
|
||||
if (ex->lhs() && ex->rhs())
|
||||
{
|
||||
if (ex->lhs()->variant() == KEYWORD_VAL)
|
||||
{
|
||||
SgKeywordValExp* key = (SgKeywordValExp*)(ex->lhs());
|
||||
if (key->value() == string("fmt"))
|
||||
if (ex->rhs()->variant() == STRING_VAL)
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
break;
|
||||
list = list->rhs();
|
||||
}
|
||||
|
||||
//check A(i,j) for example
|
||||
auto item = stIO->itemList()->lhs();
|
||||
if (item->rhs() || item->lhs())
|
||||
ok = false;
|
||||
|
||||
if (!ok)
|
||||
findArrayRefInIO(item, deprecatedByIO, stIO, currMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSPF_stat(st) && !isDVM_stat(st))
|
||||
{
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
if (st->variant() == PROC_STAT)
|
||||
{
|
||||
SgCallStmt* funcExp = (SgCallStmt*)st;
|
||||
const string fName = funcExp->symbol()->identifier();
|
||||
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
|
||||
{
|
||||
findArrayRefs(funcExp->arg(z), st, fName, z, true,
|
||||
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
isSgExecutableStatement(st) ? true : false, currFunctionName,
|
||||
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(st->expr(i), st, "", -1, (st->variant() == ASSIGN_STAT && i == 0) ? true : false,
|
||||
commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
isSgExecutableStatement(st) ? true : false, currFunctionName,
|
||||
regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, saveAllLocals,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
|
||||
//preprocess only module declaration
|
||||
for (auto& mod : modules)
|
||||
{
|
||||
SgStatement* st = mod->lexNext();
|
||||
SgStatement* lastNode = mod->lastNodeOfStmt();
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
set<string> funcParNames;
|
||||
|
||||
fillFromModule(st->symbol(), privatesByModule, privates);
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSPF_stat(st) && !isDVM_stat(st))
|
||||
{
|
||||
//TODO: set clear regions for modules
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, st->fileName(), st->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(st->expr(i), st, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
false, "NULL", regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
|
||||
currMessages, countErrors);
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
|
||||
//preprocess only block data declaration
|
||||
for (SgStatement* st = file->firstStatement()->lexNext(); st; st = st->lastNodeOfStmt(), st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == BLOCK_DATA)
|
||||
{
|
||||
SgStatement* last = st->lastNodeOfStmt();
|
||||
SgStatement* curr = st;
|
||||
|
||||
map<string, vector<SgExpression*>> commonBlocks;
|
||||
getCommonBlocksRef(commonBlocks, st, last);
|
||||
|
||||
set<string> privates;
|
||||
set<string> deprecatedByIO;
|
||||
set<string> funcParNames;
|
||||
|
||||
string blockName = "BLOCK DATA";
|
||||
if (st->symbol())
|
||||
blockName = st->symbol()->identifier();
|
||||
|
||||
while (curr && curr != last)
|
||||
{
|
||||
//TODO: set clear regions for block data
|
||||
set<ParallelRegion*> currRegs = getAllRegionsByLine(regions, curr->fileName(), curr->lineNumber());
|
||||
vector<string> regNames;
|
||||
for (auto& reg : currRegs)
|
||||
regNames.push_back(reg->GetName());
|
||||
if (regNames.size() == 0)
|
||||
regNames.push_back("default");
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
findArrayRefs(curr->expr(i), curr, "", -1, false, commonBlocks, declaredArrays, declaratedArraysSt, privates, deprecatedByIO,
|
||||
false, blockName, regNames, funcParNames, ompThreadPrivate, distrStateFromGUI, false,
|
||||
currMessages, countErrors);
|
||||
curr = curr->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
return countErrors;
|
||||
}
|
||||
292
src/Distribution/Arrays.h
Normal file
292
src/Distribution/Arrays.h
Normal file
@@ -0,0 +1,292 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "Array.h"
|
||||
|
||||
#define MAP std::map
|
||||
#define SET std::set
|
||||
#define VECTOR std::vector
|
||||
#define STRING std::string
|
||||
#define PAIR std::pair
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType>
|
||||
class Arrays
|
||||
{
|
||||
private:
|
||||
unsigned nextVertexNum;
|
||||
|
||||
MAP<Array*, VECTOR<vType>> numVertsInGraph;
|
||||
MAP<STRING, Array*> arraysByName;
|
||||
SET<Array*> arrays;
|
||||
VECTOR<STRING> arrayNameByVertex;
|
||||
VECTOR<PAIR<int, Array*>> arrayDimInfoByVertex;
|
||||
public:
|
||||
Arrays() { nextVertexNum = 0; }
|
||||
|
||||
Arrays(const Arrays ©)
|
||||
{
|
||||
nextVertexNum = copy.nextVertexNum;
|
||||
numVertsInGraph = copy.numVertsInGraph;
|
||||
arraysByName = copy.arraysByName;
|
||||
arrays = copy.arrays;
|
||||
arrayNameByVertex = copy.arrayNameByVertex;
|
||||
arrayDimInfoByVertex = copy.arrayDimInfoByVertex;
|
||||
}
|
||||
|
||||
void UpdateLinks(const MAP<Array*, Array*> &oldNewArrays)
|
||||
{
|
||||
SET<Array*> newArrays;
|
||||
for (auto &array : arrays)
|
||||
newArrays.insert(oldNewArrays.find(array)->second);
|
||||
arrays = newArrays;
|
||||
|
||||
for (auto &elem : arraysByName)
|
||||
elem.second = oldNewArrays.find(elem.second)->second;
|
||||
|
||||
for (auto &elem : arrayDimInfoByVertex)
|
||||
elem.second = oldNewArrays.find(elem.second)->second;
|
||||
|
||||
MAP<Array*, VECTOR<vType>> newNumVertsInGraph;
|
||||
for (auto &elem : numVertsInGraph)
|
||||
newNumVertsInGraph.insert(std::make_pair(oldNewArrays.find(elem.first)->second, elem.second));
|
||||
numVertsInGraph = newNumVertsInGraph;
|
||||
}
|
||||
|
||||
void cleanData()
|
||||
{
|
||||
nextVertexNum = 0;
|
||||
numVertsInGraph.clear();
|
||||
arraysByName.clear();
|
||||
arrays.clear();
|
||||
arrayNameByVertex.clear();
|
||||
arrayDimInfoByVertex.clear();
|
||||
}
|
||||
|
||||
int AddArrayToGraph(Array *array)
|
||||
{
|
||||
int status = 0;
|
||||
auto foundIt = numVertsInGraph.find(array);
|
||||
if (foundIt == numVertsInGraph.end())
|
||||
{
|
||||
const int dimSize = array->GetDimSize();
|
||||
VECTOR<vType> vertexNum(dimSize);
|
||||
|
||||
for (int i = 0; i < dimSize; ++i)
|
||||
{
|
||||
vertexNum[i] = nextVertexNum + i;
|
||||
|
||||
STRING newName(array->GetName());
|
||||
newName += "." + std::to_string(i);
|
||||
arrayNameByVertex.push_back(newName);
|
||||
arrayDimInfoByVertex.push_back(std::make_pair(i, array));
|
||||
}
|
||||
|
||||
nextVertexNum += dimSize;
|
||||
numVertsInGraph.insert(foundIt, make_pair(array, vertexNum));
|
||||
arrays.insert(array);
|
||||
arraysByName.insert(arraysByName.end(), make_pair(array->GetName(), array));
|
||||
}
|
||||
else
|
||||
status = 1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int GetVertNumber(Array *array, const int dimNum, vType &retVal) const
|
||||
{
|
||||
int err = 0;
|
||||
auto foundIt = numVertsInGraph.find(array);
|
||||
if (foundIt == numVertsInGraph.end())
|
||||
err = -1;
|
||||
else
|
||||
{
|
||||
const int maxDims = array->GetDimSize();
|
||||
if (dimNum >= maxDims)
|
||||
err = -1;
|
||||
else
|
||||
retVal = foundIt->second[dimNum];
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int GetAllVertNumber(const Array *array, std::vector<vType> &retVal) const
|
||||
{
|
||||
int err = 0;
|
||||
auto foundIt = numVertsInGraph.find((Array*)array);
|
||||
if (foundIt == numVertsInGraph.end())
|
||||
err = -1;
|
||||
else
|
||||
retVal = foundIt->second;
|
||||
return err;
|
||||
}
|
||||
|
||||
int GetDimNumber(const Array *array, const vType vertexN, vType &retVal) const
|
||||
{
|
||||
int err = 0;
|
||||
auto foundIt = numVertsInGraph.find((Array*)array);
|
||||
if (foundIt == numVertsInGraph.end())
|
||||
err = -1;
|
||||
else
|
||||
{
|
||||
const int maxDims = array->GetDimSize();
|
||||
for (int i = 0; i < maxDims; ++i)
|
||||
{
|
||||
if (foundIt->second[i] == vertexN)
|
||||
{
|
||||
retVal = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
err = -1;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int GetNameByVertex(const vType vert, STRING &name) const
|
||||
{
|
||||
if (vert >= (vType)arrayNameByVertex.size())
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
name = arrayNameByVertex[vert];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Array* GetArrayByVertex(const vType vert) const
|
||||
{
|
||||
STRING name;
|
||||
int res = GetNameByVertex(vert, name);
|
||||
Array *retVal = NULL;
|
||||
|
||||
if (res != -1)
|
||||
{
|
||||
int count = 0;
|
||||
for (int k = (int)name.size() - 1; k >= 0; --k, ++count)
|
||||
{
|
||||
if (name[k] == '.')
|
||||
{
|
||||
name[k] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
name.resize(name.size() - count - 1);
|
||||
retVal = GetArrayByName(name);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
Array* GetArrayByName(const STRING &name) const
|
||||
{
|
||||
auto res = arraysByName.find(name);
|
||||
if (res != arraysByName.end())
|
||||
return res->second;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GetInfoByVertex(const vType vertex, std::pair<int, Array*> &info) const
|
||||
{
|
||||
int err = (arrayDimInfoByVertex.size() >= vertex) ? 1 : 0;
|
||||
if (arrayDimInfoByVertex.size() < vertex)
|
||||
info = arrayDimInfoByVertex[vertex];
|
||||
return err;
|
||||
}
|
||||
|
||||
const SET<Array*>& GetArrays() const { return arrays; }
|
||||
|
||||
unsigned GetMaxVertexNum() const { return nextVertexNum; }
|
||||
|
||||
void SaveArraysToFile(FILE *file) const
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
fprintf(file, "%d\n", nextVertexNum);
|
||||
int count = numVertsInGraph.size();
|
||||
fprintf(file, "%d\n", count);
|
||||
for (auto &elem : numVertsInGraph)
|
||||
{
|
||||
fprintf(file, "%d\n", elem.first->GetArrayUniqKey().size());
|
||||
fprintf(file, "%s\n", elem.first->GetArrayUniqKey().c_str());
|
||||
int dimCount = elem.second.size();
|
||||
fprintf(file, "%d\n", dimCount);
|
||||
for (int z = 0; z < dimCount; ++z)
|
||||
fprintf(file, "%d\n", elem.second[z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//load and check
|
||||
bool LoadArraysFromFile(FILE *file, const SET<Array*> &currArrays, const int nextVertexNumOld)
|
||||
{
|
||||
bool status = true;
|
||||
if (file)
|
||||
{
|
||||
char tmpChar;
|
||||
MAP<STRING, Array*> keys;
|
||||
for (auto &elem : currArrays)
|
||||
keys.insert(std::make_pair(elem->GetArrayUniqKey(), elem));
|
||||
|
||||
fscanf(file, "%d", &nextVertexNum);
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
if (nextVertexNumOld != nextVertexNum)
|
||||
return false;
|
||||
|
||||
int count;
|
||||
fscanf(file, "%d", &count);
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int strLen = 0;
|
||||
fscanf(file, "%d", &strLen);
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
|
||||
STRING uniqKey = "";
|
||||
for (int k = 0; k < strLen; ++k)
|
||||
{
|
||||
char symb;
|
||||
fscanf(file, "%c", &symb);
|
||||
uniqKey += symb;
|
||||
}
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
|
||||
int dimCount = 0;
|
||||
fscanf(file, "%d", &dimCount);
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
VECTOR<vType> tmp(dimCount);
|
||||
for (int z = 0; z < dimCount; ++z)
|
||||
{
|
||||
fscanf(file, "%d", &(tmp[z]));
|
||||
fscanf(file, "%c", &tmpChar);
|
||||
}
|
||||
|
||||
auto found = keys.find(uniqKey);
|
||||
if (found == keys.end())
|
||||
{
|
||||
status = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
numVertsInGraph.insert(std::make_pair(found->second, tmp));
|
||||
arraysByName.insert(std::make_pair(found->second->GetName(), found->second));
|
||||
arrays.insert(found->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
status = false;
|
||||
return status;
|
||||
}
|
||||
};
|
||||
}
|
||||
#undef MAP
|
||||
#undef SET
|
||||
#undef VECTOR
|
||||
#undef STRING
|
||||
#undef PAIR
|
||||
648
src/Distribution/CreateDistributionDirs.cpp
Normal file
648
src/Distribution/CreateDistributionDirs.cpp
Normal file
@@ -0,0 +1,648 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <climits>
|
||||
|
||||
#include "Distribution.h"
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::string;
|
||||
using std::get;
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::tuple;
|
||||
|
||||
static set<DIST::Array*> arraysWithErrors;
|
||||
void checkDimsSizeOfArrays(const DIST::Arrays<int> &allArrays, map<string, vector<Messages>> &allMessages,
|
||||
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
const set<DIST::Array*> &arraysBase = allArrays.GetArrays();
|
||||
set<DIST::Array*> arrays;
|
||||
|
||||
for (auto &array : arraysBase)
|
||||
getRealArrayRefs(array, array, arrays, arrayLinksByFuncCalls);
|
||||
|
||||
bool ok = true;
|
||||
for (auto &array : arrays)
|
||||
{
|
||||
const vector<pair<int, int>> &sizes = array->GetSizes();
|
||||
for (int k = 0; k < sizes.size(); ++k)
|
||||
{
|
||||
if (sizes[k].first == -1 && sizes[k].second == -1)
|
||||
{
|
||||
// parallize this loops with TIE regime
|
||||
if (array->IsLoopArray())
|
||||
continue;
|
||||
|
||||
if (arraysWithErrors.find(array) == arraysWithErrors.end())
|
||||
{
|
||||
auto declPlaces = array->GetDeclInfo();
|
||||
for (auto &place : declPlaces)
|
||||
{
|
||||
string declF = place.first;
|
||||
int declL = place.second;
|
||||
|
||||
char buf[256];
|
||||
if (array->IsLoopArray())
|
||||
sprintf(buf, "More information is required about sizes of loop '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
|
||||
else
|
||||
sprintf(buf, "More information is required about sizes of array '%s', decl line %d, decl file %s\n", array->GetShortName().c_str(), declL, declF.c_str());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
arraysWithErrors.insert(array);
|
||||
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"More information is required about sizes of array '%s'", to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
if (array->IsLoopArray())
|
||||
__spf_printToLongBuf(bufR, R149, to_wstring(array->GetShortName()).c_str());
|
||||
else
|
||||
__spf_printToLongBuf(bufR, R37, to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
getObjectForFileFromMap(declF.c_str(), allMessages).push_back(Messages(ERROR, declL, bufR, bufE, 1012));
|
||||
}
|
||||
}
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "Can not create distribution - unknown sizes\n");
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
throw(-1);
|
||||
}
|
||||
}
|
||||
|
||||
#define WITH_REMOVE 0
|
||||
static int templateCount = 0;
|
||||
static DIST::Array* createTemplate(DIST::Array *distArray, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
|
||||
bool isMpiProgram, const map<DIST::Array*, set<DIST::Array*>>& mapOfRealRefs)
|
||||
{
|
||||
// find not connected dimentions and deprecate them
|
||||
vector<int> vInGraph;
|
||||
int err = allArrays.GetAllVertNumber(distArray, vInGraph);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
#if WITH_REMOVE
|
||||
if (!distArray->IsLoopArray())
|
||||
{
|
||||
int countOfDepr = 0;
|
||||
for (int z = 0; z < vInGraph.size(); ++z)
|
||||
{
|
||||
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
|
||||
if (count <= 0)
|
||||
countOfDepr++;
|
||||
}
|
||||
|
||||
if (countOfDepr == distArray->GetDimSize())
|
||||
{
|
||||
for (int z = 0; z < distArray->GetDimSize(); ++z)
|
||||
{
|
||||
if (!distArray->IsDimMapped(z))
|
||||
distArray->DeprecateDimension(z);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int z = 0; z < vInGraph.size(); ++z)
|
||||
{
|
||||
int count = reducedG.CountOfConnectedForArray(vInGraph[z]);
|
||||
if (count <= 0)
|
||||
distArray->DeprecateDimension(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DIST::Array *templ = new DIST::Array(*distArray);
|
||||
templ->ChangeName("dvmh_temp" + std::to_string(templateCount++));
|
||||
templ->SetId(0);
|
||||
templ->SetTemplateFlag(true);
|
||||
|
||||
if (distArray->IsLoopArray())
|
||||
for (int z = 0; z < templ->GetDimSize(); ++z)
|
||||
templ->SetMappedDim(z);
|
||||
templ->SetDimSizesToMaxMin(true);
|
||||
|
||||
bool ifRemAll = false;
|
||||
#if WITH_REMOVE
|
||||
ifRemAll = templ->RemoveUnpammedDims();
|
||||
#endif
|
||||
|
||||
set<DIST::Array*> sameArrays;
|
||||
for (auto& elem : mapOfRealRefs)
|
||||
{
|
||||
for (auto& array : elem.second)
|
||||
{
|
||||
if (array == distArray)
|
||||
{
|
||||
sameArrays = elem.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sameArrays.size())
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0, templIdx = 0; i < distArray->GetDimSize(); ++i)
|
||||
{
|
||||
int vert = -1;
|
||||
const int err = allArrays.GetVertNumber(distArray, i, vert);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
pair<DIST::Array*, int> result = make_pair(distArray, i);
|
||||
if (!isMpiProgram)
|
||||
{
|
||||
set<int> wasDone;
|
||||
reducedG.FindLinkWithMaxDim(vert, allArrays, result, wasDone);
|
||||
}
|
||||
|
||||
const bool isMapped = distArray->IsDimMapped(i);
|
||||
const bool isLoop = distArray->IsLoopArray();
|
||||
const bool notDeprecated = isMpiProgram ? true : !distArray->IsDimDepracated(i);
|
||||
if ((isMapped || isLoop) && notDeprecated)
|
||||
{
|
||||
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
if (result.first != distArray)
|
||||
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
|
||||
|
||||
if (isMpiProgram)
|
||||
for (auto& same: sameArrays)
|
||||
if (same != result.first)
|
||||
AddArrayAccess(reducedG, allArrays, templ, same, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
templIdx++;
|
||||
}
|
||||
#if !WITH_REMOVE
|
||||
else
|
||||
{
|
||||
templ->ExtendDimSize(templIdx++, make_pair(1, 1));
|
||||
__spf_print(1, "template %s was not added to graph!\n", templ->GetShortName().c_str());
|
||||
}
|
||||
#else
|
||||
else
|
||||
{
|
||||
if (ifRemAll)
|
||||
{
|
||||
AddArrayAccess(reducedG, allArrays, templ, result.first, make_pair(templIdx, result.second), 1.0, make_pair(make_pair(1, 0), make_pair(1, 0)), RR_link);
|
||||
templ->DeprecateDimension(i, false);
|
||||
if (result.first != distArray)
|
||||
templ->ExtendDimSize(templIdx, result.first->GetSizes()[result.second]);
|
||||
templIdx++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return templ;
|
||||
}
|
||||
#undef WITH_REMOVE
|
||||
|
||||
static vector<DIST::Array*> GetArrayWithMaximumDim(const vector<DIST::Array*> &arrays)
|
||||
{
|
||||
int maxDimSize = -1;
|
||||
vector<DIST::Array*> retVal;
|
||||
|
||||
for (int i = 0; i < arrays.size(); ++i)
|
||||
{
|
||||
DIST::Array *tmp = arrays[i];
|
||||
if (maxDimSize < tmp->GetDimSize())
|
||||
{
|
||||
maxDimSize = tmp->GetDimSize();
|
||||
retVal.clear();
|
||||
retVal.push_back(tmp);
|
||||
}
|
||||
else if (maxDimSize == tmp->GetDimSize())
|
||||
{
|
||||
const vector<pair<int, int>> &size1 = retVal.back()->GetSizes();
|
||||
const vector<pair<int, int>> &size2 = tmp->GetSizes();
|
||||
|
||||
if (size1 == size2)
|
||||
retVal.push_back(tmp);
|
||||
else
|
||||
{
|
||||
bool ifGT = true;
|
||||
for (int k = 0; k < size1.size(); ++k)
|
||||
if ((size1[k].second - size1[k].first) + 1 > (size2[k].second - size2[k].first) + 1)
|
||||
ifGT = false;
|
||||
|
||||
if (ifGT)
|
||||
{
|
||||
retVal.clear();
|
||||
retVal.push_back(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void convertTrees(const map<DIST::Array*, int> &treesIn, map<int, vector<DIST::Array*>> &treesOut,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
for (auto it = treesIn.begin(); it != treesIn.end(); ++it)
|
||||
{
|
||||
auto foundIt = treesOut.find(it->second);
|
||||
if (foundIt == treesOut.end())
|
||||
foundIt = treesOut.insert(foundIt, make_pair(it->second, vector<DIST::Array*>()));
|
||||
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(it->first, it->first, realRefs, arrayLinksByFuncCalls);
|
||||
for (auto &array : realRefs)
|
||||
foundIt->second.push_back(array);
|
||||
}
|
||||
}
|
||||
|
||||
static DIST::Array* findBestInEqual(vector<DIST::Array*> &arrays, DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays)
|
||||
{
|
||||
DIST::Array *retVal = NULL;
|
||||
vector<vector<attrType>> coefsByDims;
|
||||
for (auto &array : arrays)
|
||||
{
|
||||
vector<int> verts;
|
||||
int err = allArrays.GetAllVertNumber(array, verts);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
if (retVal == NULL)
|
||||
{
|
||||
retVal = array;
|
||||
for (auto &V : verts)
|
||||
coefsByDims.push_back(reducedG.GetAllAttributes(V));
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<vector<attrType>> toCmp;
|
||||
for (auto &V : verts)
|
||||
toCmp.push_back(reducedG.GetAllAttributes(V));
|
||||
for (int z = 0; z < toCmp.size(); ++z)
|
||||
{
|
||||
if (toCmp[z].size() && coefsByDims[z].size())
|
||||
{
|
||||
if (toCmp[z].back().first.first > coefsByDims[z].back().first.first)
|
||||
{
|
||||
coefsByDims = toCmp;
|
||||
retVal = array;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static bool ArraySortFunc(DIST::Array *i, DIST::Array *j) { return (i->GetName() < j->GetName()); }
|
||||
|
||||
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays, DataDirective &dataDirectives, map<string, vector<Messages>> &allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, bool isMpiProgram, set<DIST::Array*> onlyThese)
|
||||
{
|
||||
checkDimsSizeOfArrays(allArrays, allMessages, arrayLinksByFuncCalls);
|
||||
|
||||
map<DIST::Array*, int> trees;
|
||||
map<int, vector<DIST::Array*>> convTrees;
|
||||
|
||||
int countTrees = reducedG.FindAllArraysTrees(trees, allArrays);
|
||||
//create one tree for all array that not found
|
||||
bool hasTemplates = false;
|
||||
map<DIST::Array*, set<DIST::Array*>> mapOfRealRefs;
|
||||
|
||||
for (auto &arrayPair : sortArraysByName(allArrays.GetArrays()))
|
||||
{
|
||||
DIST::Array* array = arrayPair.second;
|
||||
if (onlyThese.size())
|
||||
if (onlyThese.find(array) == onlyThese.end())
|
||||
continue;
|
||||
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
|
||||
mapOfRealRefs[array] = realRefs;
|
||||
|
||||
for (auto &realArray : realRefs)
|
||||
{
|
||||
hasTemplates = hasTemplates || realArray->IsTemplate();
|
||||
auto it = trees.find(realArray);
|
||||
if (it == trees.end())
|
||||
trees.insert(it, make_pair(realArray, ++countTrees));
|
||||
}
|
||||
}
|
||||
|
||||
vector<DIST::Array*> arraysToDist;
|
||||
if (hasTemplates == false)
|
||||
{
|
||||
convertTrees(trees, convTrees, arrayLinksByFuncCalls);
|
||||
for (auto& tree : convTrees)
|
||||
{
|
||||
sort(tree.second.begin(), tree.second.end(), ArraySortFunc);
|
||||
|
||||
vector<DIST::Array*> distrArrayV = GetArrayWithMaximumDim(tree.second);
|
||||
if (distrArrayV.size() == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
DIST::Array *distrArray = findBestInEqual(distrArrayV, reducedG, allArrays);
|
||||
|
||||
DIST::Array *templ = createTemplate(distrArray, reducedG, allArrays, isMpiProgram, mapOfRealRefs);
|
||||
checkNull(templ, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
arraysToDist.push_back(templ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto &array : sortArraysByName(allArrays.GetArrays()))
|
||||
{
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(array.second, array.second, realRefs, arrayLinksByFuncCalls);
|
||||
|
||||
for (auto &realArray : sortArraysByName(realRefs))
|
||||
if (realArray.second->IsTemplate())
|
||||
arraysToDist.push_back(realArray.second);
|
||||
}
|
||||
}
|
||||
|
||||
sort(arraysToDist.begin(), arraysToDist.end(), ArraySortFunc);
|
||||
if (arraysToDist.size())
|
||||
dataDirectives.createDirstributionVariants(arraysToDist);
|
||||
}
|
||||
|
||||
|
||||
static bool createNewAlignRule(DIST::Array *alignArray, const DIST::Arrays<int> &allArrays,
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>> &rules,
|
||||
DataDirective &dataDirectives, map<string, vector<Messages>>& SPF_messages, bool withErrors = true)
|
||||
{
|
||||
DIST::Array *alignWith = NULL;
|
||||
bool hasFreeDims = false;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (alignWith == NULL && get<0>(rules[i]) != NULL)
|
||||
alignWith = get<0>(rules[i]);
|
||||
else if (alignWith != get<0>(rules[i]) && get<0>(rules[i]) != NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (get<0>(rules[i]) == NULL)
|
||||
hasFreeDims = true;
|
||||
}
|
||||
|
||||
//TODO:
|
||||
if (alignWith == NULL)
|
||||
{
|
||||
auto allDecl = alignArray->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"Can not find align rules for array '%s'", to_wstring(alignArray->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R171, to_wstring(alignArray->GetShortName()).c_str());
|
||||
if (withErrors)
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
|
||||
__spf_print(1, "can not find align rules for array '%s' (full name '%s')\n", alignArray->GetShortName().c_str(), alignArray->GetName().c_str());
|
||||
}
|
||||
if (alignWith == NULL)
|
||||
return true;
|
||||
//checkNull(alignWith, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (hasFreeDims)
|
||||
{
|
||||
set<int> usedVertDims;
|
||||
vector<int> allInAlign;
|
||||
allArrays.GetAllVertNumber(alignWith, allInAlign);
|
||||
int countOfFree = 0;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (get<0>(rules[i]) != NULL)
|
||||
usedVertDims.insert(get<1>(rules[i]));
|
||||
else
|
||||
countOfFree++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < allInAlign.size(); ++i)
|
||||
{
|
||||
if (usedVertDims.find(allInAlign[i]) != usedVertDims.end())
|
||||
{
|
||||
allInAlign.erase(allInAlign.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (allInAlign.size() >= countOfFree)
|
||||
{
|
||||
int k = 0;
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (get<0>(rules[i]) == NULL || alignArray->IsDimDepracated(i))
|
||||
{
|
||||
rules[i] = make_tuple(alignWith, allInAlign[k], make_pair(0, 0));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AlignRule newRule;
|
||||
newRule.alignArray = alignArray;
|
||||
newRule.alignWith = alignWith;
|
||||
|
||||
for (int z = 0; z < alignArray->GetDimSize(); ++z)
|
||||
{
|
||||
newRule.alignRule.push_back(make_pair(1, 0));
|
||||
|
||||
int alignToDim = -1;
|
||||
int err = allArrays.GetDimNumber(alignWith, get<1>(rules[z]), alignToDim);
|
||||
|
||||
newRule.alignRuleWith.push_back(make_pair(alignToDim, get<2>(rules[z])));
|
||||
if (get<2>(rules[z]).first == 0 && get<2>(rules[z]).second == 0)
|
||||
continue;
|
||||
|
||||
//correct template sizes
|
||||
const pair<int, int> &rule = get<2>(rules[z]);
|
||||
|
||||
if (alignWith->GetShortName().find("dvmh") != string::npos)
|
||||
{
|
||||
pair<int, int> oldSizes = alignArray->GetSizes()[z];
|
||||
if (!(oldSizes.first == oldSizes.second && oldSizes.first == -1))
|
||||
{
|
||||
oldSizes.first = oldSizes.first * rule.first + rule.second;
|
||||
oldSizes.second = oldSizes.second * rule.first + rule.second;
|
||||
alignWith->ExtendDimSize(alignToDim, oldSizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
dataDirectives.alignRules.push_back(newRule);
|
||||
return false;
|
||||
}
|
||||
|
||||
static string printRule(const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule)
|
||||
{
|
||||
string print = get<0>(rule[0])->GetShortName() + " : ";
|
||||
for (auto &elem : rule)
|
||||
print += "(" + std::to_string(get<2>(elem).first) + "," + std::to_string(get<2>(elem).second) + ")";
|
||||
return print;
|
||||
}
|
||||
|
||||
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
|
||||
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls, map<string, vector<Messages>> &SPF_messages,
|
||||
set<DIST::Array*>* canNotAlign, set<DIST::Array*> onlyThese)
|
||||
{
|
||||
set<DIST::Array*> distArrays;
|
||||
const set<DIST::Array*> &arrays = allArrays.GetArrays();
|
||||
|
||||
if (dataDirectives.distrRules.size() == 0)
|
||||
{
|
||||
for (auto &array : arrays)
|
||||
if (array->IsTemplate())
|
||||
distArrays.insert(array);
|
||||
|
||||
if (distArrays.size() == 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < dataDirectives.distrRules.size(); ++i)
|
||||
distArrays.insert(dataDirectives.distrRules[i].first);
|
||||
}
|
||||
|
||||
bool repeat = true;
|
||||
int countRep = 0;
|
||||
while (repeat)
|
||||
{
|
||||
++countRep;
|
||||
repeat = false;
|
||||
set<pair<DIST::Array*, vector<vector<tuple<DIST::Array*, int, pair<int, int>>>>>> manyDistrRules;
|
||||
int errCount = 0;
|
||||
for (auto& arrayPair : sortArraysByName(arrays))
|
||||
{
|
||||
DIST::Array* array = arrayPair.second;
|
||||
|
||||
if (sharedMemoryParallelization != 0)
|
||||
if (onlyThese.find(array) == onlyThese.end())
|
||||
continue;
|
||||
|
||||
if (distArrays.find(array) != distArrays.end())
|
||||
continue;
|
||||
|
||||
set<DIST::Array*> realArrayRefs;
|
||||
getRealArrayRefs(array, array, realArrayRefs, arrayLinksByFuncCalls);
|
||||
|
||||
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> rules(realArrayRefs.size());
|
||||
|
||||
int i = 0;
|
||||
bool allNonDistr = true;
|
||||
bool partlyNonDistr = false;
|
||||
for (auto& arrays : sortArraysByName(realArrayRefs))
|
||||
{
|
||||
int err = reducedG.GetAlignRuleWithTemplate(arrays.second, allArrays, rules[i], regionId);
|
||||
if (err == 101)
|
||||
{
|
||||
reducedG.cleanCacheLinks();
|
||||
dataDirectives.alignRules.clear();
|
||||
repeat = true;
|
||||
break;
|
||||
}
|
||||
bool nonDistr = arrays.second->IsNotDistribute();
|
||||
allNonDistr = allNonDistr && nonDistr;
|
||||
partlyNonDistr = partlyNonDistr || nonDistr;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (repeat)
|
||||
break;
|
||||
|
||||
if (allNonDistr)
|
||||
continue;
|
||||
if (partlyNonDistr)
|
||||
{
|
||||
__spf_print(1, "detected distributed and non distributed array links by function's calls for array %s\n", array->GetName().c_str());
|
||||
auto allDecl = array->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"detected distributed and non distributed array links by function's calls for array '%s'\n", to_wstring(array->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R140, to_wstring(array->GetShortName()).c_str());
|
||||
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
|
||||
for (auto& realR : realArrayRefs)
|
||||
{
|
||||
if (realR != array)
|
||||
{
|
||||
auto allDecl = realR->GetDeclInfo();
|
||||
for (auto& decl : allDecl)
|
||||
{
|
||||
std::wstring bufE, bufR;
|
||||
if (realR->IsNotDistribute())
|
||||
{
|
||||
__spf_printToLongBuf(bufE, L"detected non distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R153, to_wstring(realR->GetShortName()).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_printToLongBuf(bufE, L"detected distributed array '%s' passed as a parameter to the procedure\n", to_wstring(realR->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R141, to_wstring(realR->GetShortName()).c_str());
|
||||
}
|
||||
getObjectForFileFromMap(decl.first.c_str(), SPF_messages).push_back(Messages(ERROR, decl.second, bufR, bufE, 3020));
|
||||
}
|
||||
}
|
||||
}
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
if (isAllRulesEqualWithoutArray(rules) || sharedMemoryParallelization != 0)
|
||||
{
|
||||
bool hasError = createNewAlignRule(array, allArrays, rules[0], dataDirectives, SPF_messages, canNotAlign == NULL);
|
||||
if (hasError)
|
||||
{
|
||||
if (canNotAlign)
|
||||
canNotAlign->insert(array);
|
||||
errCount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
manyDistrRules.insert(make_pair(array, rules));
|
||||
}
|
||||
|
||||
if (errCount > 0 && canNotAlign == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (countRep > 500)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (repeat)
|
||||
continue;
|
||||
|
||||
if (manyDistrRules.size() > 0)
|
||||
{
|
||||
for (auto &array : manyDistrRules)
|
||||
{
|
||||
__spf_print(1, "different align rules for array %s was found\n", array.first->GetName().c_str());
|
||||
for (auto &rule : array.second)
|
||||
__spf_print(1, " -> %s\n", printRule(rule).c_str());
|
||||
|
||||
std::wstring bufE, bufR;
|
||||
__spf_printToLongBuf(bufE, L"different align rules for array %s were found\n", to_wstring(array.first->GetShortName()).c_str());
|
||||
__spf_printToLongBuf(bufR, R142, to_wstring(array.first->GetShortName()).c_str());
|
||||
for (auto &declPlace : array.first->GetDeclInfo())
|
||||
getObjectForFileFromMap(declPlace.first.c_str(), SPF_messages).push_back(Messages(ERROR, declPlace.second, bufR, bufE, 3020));
|
||||
}
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
13
src/Distribution/CreateDistributionDirs.h
Normal file
13
src/Distribution/CreateDistributionDirs.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops.h"
|
||||
#include "../Utils/errors.h"
|
||||
|
||||
void createDistributionDirs(DIST::GraphCSR<int, double, attrType> &reducedG, DIST::Arrays<int> &allArrays,
|
||||
DataDirective &dataDirectives, std::map<std::string, std::vector<Messages>> &allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, bool isMpiProgram, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
|
||||
int createAlignDirs(DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays, DataDirective &dataDirectives,
|
||||
const uint64_t regionId, const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCall, std::map<std::string,
|
||||
std::vector<Messages>> &SPF_messages, std::set<DIST::Array*>* canNotAlign = NULL, std::set<DIST::Array*> onlyThese = std::set<DIST::Array*>());
|
||||
void checkDimsSizeOfArrays(const DIST::Arrays<int>& allArrays, std::map<std::string, std::vector<Messages>>& allMessages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
|
||||
122
src/Distribution/Cycle.cpp
Normal file
122
src/Distribution/Cycle.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Cycle.h"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info)
|
||||
{
|
||||
Arcs.push_back(newAcr);
|
||||
wArcs.push_back(wArc);
|
||||
attrArcs.push_back(attrArc);
|
||||
compressedInfo.push_back(info);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const pair<vType, vType> &newAcr, const pair<wType, attrType> ¶mArc, const unsigned info)
|
||||
{
|
||||
AddArc(newAcr, paramArc.first, paramArc.second, info);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const vType V1, const vType V2, const pair<wType, attrType> ¶mArc, const unsigned info)
|
||||
{
|
||||
AddArc(std::make_pair(V1, V2), paramArc.first, paramArc.second, info);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
AddArc(const vType V1, const vType V2, const wType wArc, const attrType &attrArc, const unsigned info)
|
||||
{
|
||||
AddArc(std::make_pair(V1, V2), wArc, attrArc, info);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
wType Cycle<vType, wType, attrType>::
|
||||
GetCycleSum() const
|
||||
{
|
||||
wType sum = 0.0;
|
||||
for (vType i = 0; i < (vType)Arcs.size(); ++i)
|
||||
sum += wArcs[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
SortArcs()
|
||||
{
|
||||
vector<pair<wType, vType>> toSort;
|
||||
// sort by key
|
||||
for (vType i = 0; i < (vType)wArcs.size(); ++i)
|
||||
toSort.push_back(std::make_pair(wArcs[i], i));
|
||||
sort(toSort.begin(), toSort.end(), comparator);
|
||||
|
||||
vector<pair<vType, vType>> new_Arcs(wArcs.size());
|
||||
vector<wType> new_wArcs(wArcs.size());
|
||||
vector<attrType> new_attrArcs(wArcs.size());
|
||||
vector<unsigned> new_info(wArcs.size());
|
||||
|
||||
// complete sorting
|
||||
for (vType i = 0; i < (vType)wArcs.size(); ++i)
|
||||
{
|
||||
const vType idx = toSort[i].second;
|
||||
new_Arcs[i] = Arcs[idx];
|
||||
new_wArcs[i] = wArcs[idx];
|
||||
new_attrArcs[i] = attrArcs[idx];
|
||||
|
||||
if (compressedInfo.size())
|
||||
new_info[i] = compressedInfo[idx];
|
||||
}
|
||||
|
||||
attrArcs = new_attrArcs;
|
||||
wArcs = new_wArcs;
|
||||
Arcs = new_Arcs;
|
||||
compressedInfo = new_info;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
bool Cycle<vType, wType, attrType>::
|
||||
operator<(const Cycle<vType, wType, attrType> &right) const
|
||||
{
|
||||
return this->GetCycleSum() > right.GetCycleSum();
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
PrintValue() const
|
||||
{
|
||||
printf("acrs\n");
|
||||
for (int i = 0; i < Arcs.size(); ++i)
|
||||
printf("%d %d\n", Arcs[i].first, Arcs[i].second);
|
||||
printf("we\n");
|
||||
for (int i = 0; i < wArcs.size(); ++i)
|
||||
printf("%f\n", wArcs[i]);
|
||||
printf("attr\n");
|
||||
for (int i = 0; i < attrArcs.size(); ++i)
|
||||
printf("[%d %d] [%d %d]\n", attrArcs[i].first.first, attrArcs[i].first.second, attrArcs[i].second.first, attrArcs[i].second.second);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void Cycle<vType, wType, attrType>::
|
||||
PrintArcs() const
|
||||
{
|
||||
for (int i = 0; i < Arcs.size(); ++i)
|
||||
printf("[%d %d] ", Arcs[i].first, Arcs[i].second);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
template class Cycle<int, double, attrType>;
|
||||
}
|
||||
|
||||
51
src/Distribution/Cycle.h
Normal file
51
src/Distribution/Cycle.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../Utils/types.h"
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
class Cycle
|
||||
{
|
||||
private:
|
||||
std::vector<std::pair<vType, vType>> Arcs;
|
||||
std::vector<wType> wArcs;
|
||||
std::vector<attrType> attrArcs;
|
||||
std::vector<unsigned> compressedInfo;
|
||||
|
||||
static bool comparator(std::pair<wType, vType> left, std::pair<wType, vType> right)
|
||||
{
|
||||
return left.first < right.first;
|
||||
}
|
||||
public:
|
||||
int GetNumArcs() const { return (int)Arcs.size(); }
|
||||
const std::vector<std::pair<vType, vType>>& GetArcs() const { return Arcs; }
|
||||
const std::vector<wType>& GetWeigthsArcs() const { return wArcs; }
|
||||
const std::vector<attrType>& GetAttributesArcs() const { return attrArcs; }
|
||||
|
||||
void AddArc(const std::pair<vType, vType> &newAcr, const wType wArc, const attrType &attrArc, const unsigned info);
|
||||
void AddArc(const std::pair<vType, vType> &newAcr, const std::pair<wType, attrType> ¶mArc, const unsigned info);
|
||||
void AddArc(const vType V1, const vType V2, const std::pair<wType, attrType> ¶mArc, const unsigned info);
|
||||
void AddArc(const vType V1, const vType V2, const wType wArc, const attrType &attrArc, const unsigned info);
|
||||
wType GetCycleSum() const;
|
||||
void SortArcs();
|
||||
// sort as maximum
|
||||
bool operator<(const Cycle<vType, wType, attrType> &right) const;
|
||||
void PrintValue() const;
|
||||
void PrintArcs() const;
|
||||
const std::vector<unsigned>& GetShortInfo() const { return compressedInfo; }
|
||||
|
||||
unsigned getFullSize()
|
||||
{
|
||||
unsigned fullSize = 0;
|
||||
fullSize += (int)Arcs.capacity() * sizeof(vType) * 2;
|
||||
fullSize += (int)wArcs.capacity() * sizeof(wType);
|
||||
fullSize += (int)attrArcs.capacity() * sizeof(attrArcs);
|
||||
fullSize += (int)compressedInfo.capacity();
|
||||
return fullSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
629
src/Distribution/Distribution.cpp
Normal file
629
src/Distribution/Distribution.cpp
Normal file
@@ -0,0 +1,629 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
#if _WIN32 && NDEBUG && __BOOST
|
||||
#include <boost/thread.hpp>
|
||||
#endif
|
||||
extern int passDone;
|
||||
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::make_pair;
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using namespace std::chrono;
|
||||
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
#include "Array.h"
|
||||
#include "Distribution.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/types.h"
|
||||
#include "../Distribution/Cycle.h"
|
||||
#include "../VisualizerCalls/get_information.h"
|
||||
#include "../VisualizerCalls/SendMessage.h"
|
||||
|
||||
extern int keepFiles;
|
||||
|
||||
#define ERROR_CHECK(err) do { if (err != 0) return err; } while(0)
|
||||
#define FIRST(x) get<0>(x)
|
||||
#define SECOND(x) get<1>(x)
|
||||
#define THIRD(x) get<2>(x)
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
//fix attributes: pair< pair<int, int>, pair<int, int> >
|
||||
template<typename attrType>
|
||||
attrType shiftByDiffInArc(const attrType& arcAttr)
|
||||
{
|
||||
pair<int, int> left = arcAttr.first;
|
||||
pair<int, int> right = arcAttr.second;
|
||||
|
||||
if (left.first == right.first)
|
||||
{
|
||||
if (left.second == right.second)
|
||||
left.second = right.second = 0;
|
||||
else if (left.second != 0 && right.second != 0)
|
||||
{
|
||||
const int diffZeroL = abs(left.second - 0);
|
||||
const int diffZeroR = abs(right.second - 0);
|
||||
if (diffZeroL < diffZeroR)
|
||||
{
|
||||
if (left.second > 0)
|
||||
{
|
||||
left.second -= diffZeroL;
|
||||
right.second -= diffZeroL;
|
||||
}
|
||||
else
|
||||
{
|
||||
left.second += diffZeroL;
|
||||
right.second += diffZeroL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (right.second > 0)
|
||||
{
|
||||
left.second -= diffZeroR;
|
||||
right.second -= diffZeroR;
|
||||
}
|
||||
else
|
||||
{
|
||||
left.second += diffZeroR;
|
||||
right.second += diffZeroR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return make_pair(left, right);
|
||||
}
|
||||
|
||||
template<typename attrType>
|
||||
attrType inverseArcByShifts(const attrType& arcAttr)
|
||||
{
|
||||
pair<int, int> left = arcAttr.first;
|
||||
pair<int, int> right = arcAttr.second;
|
||||
|
||||
if (left.first == right.first)
|
||||
{
|
||||
if (left.second < 0 && right.second < 0)
|
||||
;
|
||||
else if (left.second < 0)
|
||||
{
|
||||
std::swap(left.second, right.second);
|
||||
right.second = -right.second;
|
||||
}
|
||||
else if (right.second < 0)
|
||||
{
|
||||
std::swap(left.second, right.second);
|
||||
left.second = -left.second;
|
||||
}
|
||||
}
|
||||
return make_pair(left, right);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
|
||||
Array *arr1, Array *arr2, pair<int, int> arc, wType arcWeight, const attrType &arcAttr,
|
||||
const uint8_t linkType)
|
||||
{
|
||||
int err = 0;
|
||||
allArrays.AddArrayToGraph(arr1);
|
||||
allArrays.AddArrayToGraph(arr2);
|
||||
|
||||
vType V1, V2;
|
||||
ERROR_CHECK(allArrays.GetVertNumber(arr1, arc.first, V1));
|
||||
ERROR_CHECK(allArrays.GetVertNumber(arr2, arc.second, V2));
|
||||
|
||||
G.AddToGraph(V1, V2, arcWeight, shiftByDiffInArc(arcAttr), linkType);
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static int GetIdxOfNextCycle(const vector<tuple<vType, vType, attrType>> &localDelArcs,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles,
|
||||
const vector<pair<int, int>> &indexOfConflict,
|
||||
const int idxStart = 0)
|
||||
{
|
||||
int idx = -1;
|
||||
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &currCycle = cycles[indexOfConflict[i].first];
|
||||
if (localDelArcs.size() == 0)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector<pair<vType, vType>> &arcs = currCycle.GetArcs();
|
||||
const vector<attrType> &attributes = currCycle.GetAttributesArcs();
|
||||
bool same = false;
|
||||
|
||||
for (int k = 0; k < (int)arcs.size(); ++k)
|
||||
{
|
||||
const tuple<vType, vType, attrType> toCheck = make_tuple(arcs[k].first, arcs[k].second, attributes[k]);
|
||||
const tuple<vType, vType, attrType> toCheckRev = make_tuple(arcs[k].second, arcs[k].first, make_pair(attributes[k].second, attributes[k].first));
|
||||
|
||||
same = false;
|
||||
for (int m = 0; m < (int)localDelArcs.size(); ++m)
|
||||
{
|
||||
if (toCheck == localDelArcs[m] || toCheckRev == localDelArcs[m])
|
||||
{
|
||||
same = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
break;
|
||||
}
|
||||
if (same)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static int GetIdxOfNextCycle(const unsigned *fastCache, const vector<unsigned> &localDelArcsShort,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles,
|
||||
const vector<pair<int, int>> &indexOfConflict,
|
||||
const int idxStart = 0)
|
||||
{
|
||||
int idx = -1;
|
||||
const pair<int, int> *data = indexOfConflict.data();
|
||||
for (int i = idxStart; i < (int)indexOfConflict.size(); ++i)
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &currCycle = cycles[data[i].first];
|
||||
if (localDelArcsShort.size() == 0)
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const vector<unsigned> &shortInfo = currCycle.GetShortInfo();
|
||||
bool same = false;
|
||||
for (int k = 0; k < (int)shortInfo.size(); ++k)
|
||||
{
|
||||
if (fastCache[shortInfo[k]] == 1)
|
||||
{
|
||||
same = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (same)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static inline bool checkGraphTrue(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool checkGraph(const int startV, const int realV, const GraphCSR<int, double, attrType> &G)
|
||||
{
|
||||
return realV == G.CountOfConnected(startV);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType, bool check(const int startV, const int realV, const GraphCSR<vType, wType, attrType> &G)>
|
||||
static void FindBestSequenceForDelArcs(double &globalSum, vector<tuple<vType, vType, attrType>> &globalDelArcs,
|
||||
const double localSum, vector<tuple<vType, vType, attrType>> &localDelArcs,
|
||||
vector<unsigned> &localDelArcsShort,
|
||||
unsigned *fastCache,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
|
||||
const int lastIndexOfConflict, const int countInTree,
|
||||
const GraphCSR<vType, wType, attrType> &graph)
|
||||
{
|
||||
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
|
||||
if (nextConflict == -1)
|
||||
{
|
||||
globalSum = localSum;
|
||||
globalDelArcs = localDelArcs;
|
||||
|
||||
//char buf[256];
|
||||
//sprintf(buf, " global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
|
||||
printf("SAPFOR: global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict);
|
||||
//addToGlobalBufferAndPrint(buf);
|
||||
createNeededException();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
|
||||
const vector<pair<vType, vType>> &arcs = conflicCycle.GetArcs();
|
||||
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
|
||||
const vector<wType> &weights = conflicCycle.GetWeigthsArcs();
|
||||
const vector<attrType> &attributes = conflicCycle.GetAttributesArcs();
|
||||
|
||||
for (int i = 0; i < (int)arcs.size(); ++i)
|
||||
{
|
||||
const pair<vType, vType> &currArc = arcs[i];
|
||||
const wType currW = weights[i];
|
||||
const attrType &currAttr = attributes[i];
|
||||
|
||||
if (!check(currArc.first, countInTree, graph))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (localSum + currW < globalSum)
|
||||
{
|
||||
localDelArcs.push_back(make_tuple(currArc.first, currArc.second, currAttr));
|
||||
localDelArcsShort.push_back(shortInfo[i]);
|
||||
fastCache[shortInfo[i]] = 1;
|
||||
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, check>
|
||||
(globalSum, globalDelArcs, localSum + currW, localDelArcs, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict, countInTree, graph);
|
||||
|
||||
fastCache[shortInfo[i]] = 0;
|
||||
localDelArcs.pop_back();
|
||||
localDelArcsShort.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
createNeededException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static void CountConflictVarints(int64_t &countVars,
|
||||
vector<unsigned> &localDelArcsShort, unsigned *fastCache,
|
||||
const vector<Cycle<vType, wType, attrType>> &cycles, const vector<pair<int, int>> &indexOfConflict,
|
||||
const int lastIndexOfConflict)
|
||||
{
|
||||
int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1);
|
||||
if (nextConflict == -1)
|
||||
{
|
||||
countVars++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
const Cycle<vType, wType, attrType> &conflicCycle = cycles[indexOfConflict[nextConflict].first];
|
||||
const vector<unsigned> &shortInfo = conflicCycle.GetShortInfo();
|
||||
|
||||
for (int i = 0; i < (int)shortInfo.size(); ++i)
|
||||
{
|
||||
localDelArcsShort.push_back(shortInfo[i]);
|
||||
fastCache[shortInfo[i]] = 1;
|
||||
|
||||
CountConflictVarints(countVars, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict);
|
||||
|
||||
fastCache[shortInfo[i]] = 0;
|
||||
localDelArcsShort.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define DEGUB_DEL_ALL_CYCLES 0
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static void FindNonConflictDelArcs(vector<tuple<vType, vType, attrType>> &delArcs, const vector<Cycle<vType, wType, attrType>> &cycles)
|
||||
{
|
||||
vector<pair<int, int>> idxOfLoops(cycles.size());
|
||||
// fill indexs for all lopps for using 'GetIdxOfNextCycle' procedure
|
||||
for (int i = 0; i < (int)cycles.size(); ++i)
|
||||
#if !DEGUB_DEL_ALL_CYCLES
|
||||
idxOfLoops[i] = std::make_pair(i, 0);
|
||||
#else
|
||||
{
|
||||
const std::vector<pair<vType, vType>> &arcs = cycles[i].GetArcs();
|
||||
const std::vector<attrType> &attrs = cycles[i].GetAttributesArcs();
|
||||
for (int i = 0; i < arcs.size(); ++i)
|
||||
delArcs.push_back(std::make_tuple(arcs[i].first, arcs[i].second, attrs[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !DEGUB_DEL_ALL_CYCLES
|
||||
int idxNext = -1;
|
||||
do
|
||||
{
|
||||
idxNext = GetIdxOfNextCycle(delArcs, cycles, idxOfLoops, idxNext + 1);
|
||||
if (idxNext != -1)
|
||||
{
|
||||
std::pair<vType, vType> arc = cycles[idxNext].GetArcs()[0];
|
||||
attrType attr = cycles[idxNext].GetAttributesArcs()[0];
|
||||
delArcs.push_back(std::make_tuple(arc.first, arc.second, attr));
|
||||
}
|
||||
} while (idxNext != -1);
|
||||
#endif
|
||||
}
|
||||
#undef DEGUB_DEL_ALL_CYCLES
|
||||
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
static pair<bool, double> CreateOptimalAlignementTree(GraphCSR<vType, wType, attrType> &G, const Arrays<vType> &allArrays,
|
||||
vector<tuple<vType, vType, attrType>> &toDelArcs, bool needPrint = true, bool useSavedQ = false)
|
||||
{
|
||||
double globalSum = 0;
|
||||
bool allOnlySecondType = true;
|
||||
|
||||
vector<vType> trees;
|
||||
vector<vector<vType>> vertByTrees;
|
||||
set<vType> unqieTrees = G.FindTrees(trees, vertByTrees);
|
||||
|
||||
__spf_print(needPrint, " GRAPH size: |V| = %d, |E| = %d\n", G.GetNumberOfV(), G.GetNumberOfE() / 2);
|
||||
__spf_print(needPrint, " TREES count %d\n", (int)unqieTrees.size());
|
||||
vector<unsigned char> tmp;
|
||||
for (int z = 0; z < vertByTrees.size(); ++z)
|
||||
if (vertByTrees[z].size())
|
||||
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, (int)vertByTrees[z].size(), G.MakeConnected(vertByTrees[z][0], tmp).second);
|
||||
else
|
||||
__spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, 0, 0);
|
||||
|
||||
toDelArcs = G.CreateMaximumSpanningTree();
|
||||
return make_pair(allOnlySecondType, globalSum);
|
||||
|
||||
// OLD ALGORITHM, THIS IS unreachable code !!
|
||||
vector<vector<Cycle<vType, wType, attrType>>> AllCycles;
|
||||
|
||||
G.GetAllSimpleLoops(AllCycles, needPrint, useSavedQ);
|
||||
toDelArcs.clear();
|
||||
|
||||
for (int k = 0; k < AllCycles.size(); ++k)
|
||||
{
|
||||
unsigned maxElem = 0;
|
||||
bool onlySecondConflictType = true;
|
||||
|
||||
for (auto &elem : AllCycles[k])
|
||||
for (auto &cycleShortInfo : elem.GetShortInfo())
|
||||
maxElem = std::max(maxElem, cycleShortInfo);
|
||||
|
||||
if (maxElem != 0 && needPrint)
|
||||
printf(" SAPFOR: max elem for cache %lld, in MB: %f\n", maxElem, maxElem / 1024. / 1024. * sizeof(unsigned));
|
||||
|
||||
unsigned *fastCache = new unsigned[maxElem];
|
||||
memset(fastCache, 0, sizeof(unsigned) * maxElem);
|
||||
|
||||
char buf[256];
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " PROF: [%d TREE]:\n", k);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
double globalSumLocal = (double)INT32_MAX;
|
||||
vector<pair<vType, vType>> indexOfConflict;
|
||||
vector<Cycle<vType, wType, attrType>> &cycles = AllCycles[k];
|
||||
|
||||
vector<tuple<vType, vType, attrType>> localDelArcs;
|
||||
vector<unsigned> localDelArcShort;
|
||||
|
||||
G.SortLoopsBySize(cycles, needPrint);
|
||||
G.SortLoopsByWeight(cycles, needPrint);
|
||||
|
||||
for (int i = 0; i < (int)cycles.size(); ++i)
|
||||
cycles[i].SortArcs();
|
||||
|
||||
int countConflicts = G.GetConflictCycles(cycles, allArrays, indexOfConflict, needPrint);
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " num of conflict cycles %d\n", countConflicts);
|
||||
printf("SAPFOR: num of conflict cycles %d\n", countConflicts);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
if (countConflicts != 0)
|
||||
{
|
||||
int typeConflict[2] = { 0, 0 };
|
||||
for (int i = 0; i < indexOfConflict.size(); ++i)
|
||||
typeConflict[indexOfConflict[i].second]++;
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, " num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
|
||||
printf("SAPFOR: num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]);
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
if (typeConflict[0])
|
||||
{
|
||||
onlySecondConflictType = false;
|
||||
allOnlySecondType = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
#if _WIN32
|
||||
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
|
||||
#else
|
||||
wstring treeM = L"conflict resolution, processing group " + std::to_wstring(k + 1) + L"/" + std::to_wstring(AllCycles.size());
|
||||
#endif
|
||||
sendMessage_2lvl(treeM);
|
||||
|
||||
}
|
||||
|
||||
auto timeR = steady_clock::now();
|
||||
if (countConflicts != 0)
|
||||
{
|
||||
const int countInTree = G.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first);
|
||||
const int lastIndexOfConflict = -1;
|
||||
|
||||
if (needPrint)
|
||||
printf("SAPFOR: before del %d\n", countInTree);
|
||||
|
||||
/*int64_t countVars = 0;
|
||||
CountConflictVarints(countVars, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict);
|
||||
printf("SAPFOR: count of vars %lld\n", countVars);*/
|
||||
|
||||
if (onlySecondConflictType)
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, checkGraph>
|
||||
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
|
||||
else
|
||||
FindBestSequenceForDelArcs
|
||||
<vType, wType, attrType, checkGraphTrue>
|
||||
(globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G);
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
auto tmpReducedG = G;
|
||||
tmpReducedG.RemovedEdges(toDelArcs, allArrays);
|
||||
if (needPrint)
|
||||
printf("SAPFOR: after del %d\n", tmpReducedG.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first));
|
||||
}
|
||||
globalSum += globalSumLocal;
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, "PROF: FindBestSequenceForDelArcs: %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
printf("SAPFOR: time of FindBestSequenceForDelArcs %f sec\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
timeR = steady_clock::now();
|
||||
FindNonConflictDelArcs(toDelArcs, cycles);
|
||||
if (needPrint)
|
||||
{
|
||||
sprintf(buf, "PROF: FindNonConflictDelArcs %f\n", (duration_cast<duration<double>>(steady_clock::now() - timeR)).count());
|
||||
addToGlobalBufferAndPrint(buf);
|
||||
}
|
||||
|
||||
delete []fastCache;
|
||||
}
|
||||
|
||||
if (needPrint)
|
||||
sendMessage_2lvl(L"");
|
||||
|
||||
return make_pair(allOnlySecondType, globalSum);
|
||||
}
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
|
||||
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph)
|
||||
{
|
||||
vector<tuple<int, int, attrType>> toDelArcs;
|
||||
|
||||
if (G.GetNumberOfE() == 0)
|
||||
return;
|
||||
|
||||
double globalSum = 0;
|
||||
|
||||
|
||||
string FullName = "_graph_full_reg" + std::to_string(regionNum) + ".txt";
|
||||
string ReducedName = "_graph_reduced_reg" + std::to_string(regionNum) + ".txt";
|
||||
//__spf_print(1, "flag keepFiles %d, flag onlyGraph %d\n", keepFiles, onlyGraph);
|
||||
|
||||
if (keepFiles)
|
||||
{
|
||||
if (!onlyGraph)
|
||||
G.CreateGraphWiz(FullName.c_str(), toDelArcs, allArrays, false);
|
||||
else
|
||||
G.CreateGraphWiz(FullName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
|
||||
}
|
||||
|
||||
if (!onlyGraph)
|
||||
{
|
||||
G.HighlightLinks();
|
||||
|
||||
//old simple algorithm
|
||||
//G.RemoveMultipleArcsByWeights();
|
||||
|
||||
//new algorithm with optimal strategy
|
||||
G.RemoveMultipleArcsOptimal();
|
||||
|
||||
pair<bool, double> retVal = CreateOptimalAlignementTree(G, allArrays, toDelArcs);
|
||||
globalSum = retVal.second;
|
||||
bool onlySecondType = retVal.first;
|
||||
|
||||
reducedG = G;
|
||||
reducedG.RemovedEdges(toDelArcs, allArrays);
|
||||
|
||||
double maxWeight = reducedG.CalculateSumOfWeights() + 1;
|
||||
//try to resolve conflicts of 1 type
|
||||
const set<Array*> &arrays = allArrays.GetArrays();
|
||||
|
||||
vector<Array*> arraysV;
|
||||
arraysV.assign(arrays.begin(), arrays.end());
|
||||
|
||||
for (int z = 0; z < arraysV.size(); ++z)
|
||||
{
|
||||
const DIST::Array *array = arraysV[z];
|
||||
|
||||
#ifdef _WIN32
|
||||
wstring treeM = L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
|
||||
#else
|
||||
wstring treeM = L"conflict resolution, processing array " + std::to_wstring(z + 1) + L"/" + std::to_wstring(arrays.size());
|
||||
#endif
|
||||
sendMessage_2lvl(treeM);
|
||||
|
||||
vector<vType> verts;
|
||||
|
||||
if (array->GetDimSize() == 1)
|
||||
continue;
|
||||
|
||||
int err = allArrays.GetAllVertNumber(array, verts);
|
||||
if (err != 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
attrType tmpPair = make_pair(make_pair(1, 0), make_pair(1, 0));
|
||||
|
||||
for (int i = 0; i < verts.size(); ++i)
|
||||
{
|
||||
for (int j = i + 1; j < verts.size(); ++j)
|
||||
{
|
||||
GraphCSR<vType, wType, attrType> findConflict(reducedG);
|
||||
findConflict.AddToGraph(verts[i], verts[j], maxWeight, tmpPair, WW_link);
|
||||
|
||||
vector<tuple<int, int, attrType>> toDelArcsLocal;
|
||||
globalSum = CreateOptimalAlignementTree(findConflict, allArrays, toDelArcsLocal, false, true).second;
|
||||
if (toDelArcsLocal.size() != 0)
|
||||
reducedG.RemovedEdges(toDelArcsLocal, allArrays);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendMessage_2lvl(L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
reducedG = G;
|
||||
reducedG.RemoveMultipleArcsByWeights();
|
||||
}
|
||||
|
||||
if (keepFiles)
|
||||
reducedG.CreateGraphWiz(ReducedName.c_str(), vector<tuple<int, int, attrType>>(), allArrays, true);
|
||||
}
|
||||
|
||||
template void createOptimalDistribution(GraphCSR<int, double, attrType> &G, GraphCSR<int, double, attrType> &reducedG, const Arrays<int> &allArrays, const uint64_t regionNum, bool onlyGraph);
|
||||
template int AddArrayAccess(GraphCSR<int, double, attrType> &G, Arrays<int> &allArrays, Array *arr1, Array *arr2, pair<int, int> arc, double arcWeight, const attrType &arcAttr, const uint8_t linkType);
|
||||
template attrType shiftByDiffInArc(const attrType& arcAttr);
|
||||
template attrType inverseArcByShifts(const attrType& arcAttr);
|
||||
}
|
||||
|
||||
#undef ERROR_CHECK
|
||||
#undef FIRST
|
||||
#undef SECOND
|
||||
#undef THIRD
|
||||
28
src/Distribution/Distribution.h
Normal file
28
src/Distribution/Distribution.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
#include "GraphCSR.h"
|
||||
#include "Arrays.h"
|
||||
#include "Array.h"
|
||||
|
||||
namespace DIST = Distribution;
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename attrType>
|
||||
attrType shiftByDiffInArc(const attrType& arcAttr);
|
||||
|
||||
template<typename attrType>
|
||||
attrType inverseArcByShifts(const attrType& arcAttr);
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
int AddArrayAccess(GraphCSR<vType, wType, attrType> &G, Arrays<vType> &allArrays,
|
||||
Array *arr1, Array *arr2, std::pair<int, int> arc, wType arcWeight,
|
||||
const attrType &arcAttr, const uint8_t linkType);
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
void createOptimalDistribution(GraphCSR<vType, wType, attrType> &G, GraphCSR<vType, wType, attrType> &reducedG,
|
||||
const Arrays<vType> &allArrays, const uint64_t regionNum, bool onlyGraph);
|
||||
}
|
||||
1324
src/Distribution/DvmhDirective.cpp
Normal file
1324
src/Distribution/DvmhDirective.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
src/Distribution/DvmhDirective.h
Normal file
184
src/Distribution/DvmhDirective.h
Normal file
@@ -0,0 +1,184 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "Array.h"
|
||||
#include "DvmhDirectiveBase.h"
|
||||
#include "../Utils/AstWrapper.h"
|
||||
#include "../Utils/types.h"
|
||||
#include "../Utils/utils.h"
|
||||
|
||||
extern int sharedMemoryParallelization;
|
||||
|
||||
struct LoopGraph;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
template<typename vType, typename wType, typename attrType> class GraphCSR;
|
||||
template<typename vType> class Arrays;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
struct AlignRule : public AlignRuleBase
|
||||
{
|
||||
public:
|
||||
Statement* GenRule(File *file, const int variant) const;
|
||||
};
|
||||
|
||||
struct DistrVariant : public DistrVariantBase
|
||||
{
|
||||
public:
|
||||
DistrVariant(const std::vector<dist> &distRule) : DistrVariantBase(distRule) { }
|
||||
void GenRule(File *file, Expression *arrayRef, const std::vector<int> &newOrder) const;
|
||||
std::vector<Expression*> GenRuleSt(File *file, const std::vector<int> &newOrder) const;
|
||||
};
|
||||
|
||||
struct DataDirective : Directive
|
||||
{
|
||||
public:
|
||||
std::vector<AlignRule> alignRules;
|
||||
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> distrRules;
|
||||
public:
|
||||
std::vector<std::pair<DIST::Array*, std::vector<DistrVariant>>> GetDistrRules() const { return distrRules; }
|
||||
void createDirstributionVariants(const std::vector<DIST::Array*> &arraysToDist);
|
||||
std::vector<std::string> GenRule(const std::vector<int> &rules) const;
|
||||
std::vector<std::string> GenAlignsRules() const;
|
||||
std::vector<AlignRule> GenAlignsRules(void*) { return alignRules; }
|
||||
std::vector<Statement*> GenRule(File *file, const std::vector<int> &rules, const int variant) const;
|
||||
std::vector<std::vector<dist>> GenRule(const std::vector<int> &rules, int) const;
|
||||
std::vector<Statement*> GenAlignsRules(File *file, const int variant) const;
|
||||
void UpdateLinks(const std::map<DIST::Array*, DIST::Array*> &oldNewArrays)
|
||||
{
|
||||
for (int i = 0; i < distrRules.size(); ++i)
|
||||
distrRules[i].first = oldNewArrays.find(distrRules[i].first)->second;
|
||||
}
|
||||
|
||||
~DataDirective()
|
||||
{
|
||||
for (auto &elem : distrRules)
|
||||
{
|
||||
if (elem.first && elem.first->IsTemplate())
|
||||
{
|
||||
delete elem.first;
|
||||
elem.first = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct CreatedDirective : Directive
|
||||
{
|
||||
std::string data;
|
||||
std::vector<Expression*> sageData;
|
||||
|
||||
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData) :
|
||||
data(data), sageData(sageData)
|
||||
{ }
|
||||
|
||||
explicit CreatedDirective(const std::string& data, const std::vector<Expression*>& sageData, int line) :
|
||||
data(data), sageData(sageData)
|
||||
{
|
||||
this->line = line;
|
||||
}
|
||||
};
|
||||
|
||||
struct ParallelDirective : Directive
|
||||
{
|
||||
public:
|
||||
std::vector<std::string> parallel;
|
||||
// tuple of <varName, A, B> on A*x + B
|
||||
std::vector<std::pair<std::string, std::pair<int, int>>> on;
|
||||
DIST::Array *arrayRef; // template
|
||||
|
||||
DIST::Array *arrayRef2;// main array in loop
|
||||
std::vector<std::pair<std::string, std::pair<int, int>>> on2;
|
||||
|
||||
std::string cloneOfTemplate; // if loop has realigns before
|
||||
|
||||
std::set<Symbol*> privates;
|
||||
// origin_Name uniqName bounds
|
||||
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> shadowRenew;
|
||||
std::vector<std::vector<std::pair<int, int>>> shadowRenewShifts;
|
||||
|
||||
// origin_Name uniqName bounds
|
||||
std::vector<std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>> across;
|
||||
std::vector<std::vector<std::pair<int, int>>> acrossShifts;
|
||||
// origin_Name uniqName expression
|
||||
std::map<std::pair<std::pair<std::string, std::string>, std::string>, Expression*> remoteAccess;
|
||||
|
||||
std::map<std::string, std::set<std::string>> reduction;
|
||||
std::map<std::string, std::set<std::tuple<std::string, std::string, int>>> reductionLoc;
|
||||
public:
|
||||
ParallelDirective() : arrayRef(NULL), arrayRef2(NULL) { }
|
||||
ParallelDirective(const ParallelDirective ©From) : Directive(copyFrom)
|
||||
{
|
||||
parallel = copyFrom.parallel;
|
||||
on = copyFrom.on;
|
||||
on2 = copyFrom.on2;
|
||||
|
||||
arrayRef = copyFrom.arrayRef;
|
||||
arrayRef2 = copyFrom.arrayRef2;
|
||||
|
||||
privates = copyFrom.privates;
|
||||
shadowRenew = copyFrom.shadowRenew;
|
||||
shadowRenewShifts = copyFrom.shadowRenewShifts;
|
||||
across = copyFrom.across;
|
||||
acrossShifts = copyFrom.acrossShifts;
|
||||
remoteAccess = copyFrom.remoteAccess;
|
||||
reduction = copyFrom.reduction;
|
||||
reductionLoc = copyFrom.reductionLoc;
|
||||
|
||||
cloneOfTemplate = copyFrom.cloneOfTemplate;
|
||||
}
|
||||
|
||||
//for F_LANG;
|
||||
Directive*
|
||||
genDirective(File *file, const std::vector<std::pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
LoopGraph* currLoop,
|
||||
DIST::GraphCSR<int, double, attrType> &reducedG,
|
||||
DIST::Arrays<int> &allArrays,
|
||||
const uint64_t regionId,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls);
|
||||
|
||||
friend ParallelDirective* operator+(const ParallelDirective &first, const ParallelDirective &second);
|
||||
|
||||
~ParallelDirective()
|
||||
{
|
||||
parallel.clear();
|
||||
on.clear();
|
||||
privates.clear();
|
||||
shadowRenew.clear();
|
||||
across.clear();
|
||||
acrossShifts.clear();
|
||||
reduction.clear();
|
||||
reductionLoc.clear();
|
||||
remoteAccess.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string genBounds(std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>> &shadowOp,
|
||||
std::vector<std::pair<int, int>> &shadowOpShift,
|
||||
DIST::GraphCSR<int, double, attrType> &reducedG,
|
||||
DIST::Arrays<int> &allArrays, DIST::Array* shadowArray,
|
||||
std::map<DIST::Array*, std::vector<ArrayOp>>& remoteRegularReads,
|
||||
const std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>> &readOps,
|
||||
const bool isAcross, const uint64_t regionId,
|
||||
const std::vector<std::pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
std::set<DIST::Array*> &arraysInAcross,
|
||||
std::vector<std::map<std::pair<int, int>, int>> &shiftsByAccess,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> &arrayLinksByFuncCalls) const;
|
||||
|
||||
std::string genBoundsNoDist(std::pair<std::pair<std::string, std::string>, std::vector<std::pair<int, int>>>& shadowOp,
|
||||
std::vector<std::pair<int, int>>& shadowOpShift,
|
||||
DIST::Array* currArray,
|
||||
const std::map<DIST::Array*, std::pair<std::vector<ArrayOp>, std::vector<bool>>>& readOps,
|
||||
std::set<DIST::Array*>& arraysInAcross,
|
||||
std::vector<std::map<std::pair<int, int>, int>>& shiftsByAccess,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls) const;
|
||||
};
|
||||
|
||||
std::string genStringExpr(const std::string &letter, const std::pair<int, int> expr);
|
||||
std::pair<std::string, std::string> convertDigitToPositive(const int digit);
|
||||
811
src/Distribution/DvmhDirectiveBase.cpp
Normal file
811
src/Distribution/DvmhDirectiveBase.cpp
Normal file
@@ -0,0 +1,811 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "DvmhDirective.h"
|
||||
#include "../Distribution/Array.h"
|
||||
#include "../Distribution/Arrays.h"
|
||||
#include "../Distribution/GraphCSR.h"
|
||||
#include "../Utils/errors.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
using std::vector;
|
||||
using std::tuple;
|
||||
using std::get;
|
||||
using std::string;
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::map;
|
||||
|
||||
using std::set_union;
|
||||
using std::make_pair;
|
||||
using std::min;
|
||||
using std::max;
|
||||
|
||||
template<typename setT>
|
||||
static void uniteSets(const set<setT> &first, const set<setT> &second, set<setT> &result)
|
||||
{
|
||||
vector<setT> unitedVector(first.size() + second.size());
|
||||
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
|
||||
unitedVector.resize(it - unitedVector.begin());
|
||||
for (int i = 0; i < (int)unitedVector.size(); ++i)
|
||||
result.insert(unitedVector[i]);
|
||||
}
|
||||
|
||||
template<typename keyT, typename valT>
|
||||
static void uniteSets(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
|
||||
{
|
||||
vector<pair<keyT, valT>> unitedVector(first.size() + second.size());
|
||||
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
|
||||
unitedVector.resize(it - unitedVector.begin());
|
||||
for (int i = 0; i < (int)unitedVector.size(); ++i)
|
||||
result.insert(unitedVector[i]);
|
||||
}
|
||||
|
||||
template<typename keyT, typename valT>
|
||||
static void uniteReduction(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
|
||||
{
|
||||
auto itF = first.begin();
|
||||
for (auto &redList : result)
|
||||
{
|
||||
auto itFound = second.find(redList.first);
|
||||
if (itFound != second.end())
|
||||
uniteSets(itF->second, itFound->second, redList.second);
|
||||
++itF;
|
||||
}
|
||||
|
||||
for (auto redList : second)
|
||||
{
|
||||
auto itFound = result.find(redList.first);
|
||||
if (itFound == result.end())
|
||||
result.insert(itFound, redList);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename vTuples>
|
||||
static vTuples uniteOnRules(const vTuples &first, const vTuples &second)
|
||||
{
|
||||
vTuples result(first.size());
|
||||
for (int i = 0; i < (int)first.size(); ++i)
|
||||
{
|
||||
bool firstStar = first[i].first == "*";
|
||||
bool secondStar = second[i].first == "*";
|
||||
if (firstStar && secondStar)
|
||||
result[i].first = "*";
|
||||
else if (firstStar)
|
||||
result[i] = second[i];
|
||||
else
|
||||
result[i] = first[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename vTuples>
|
||||
static bool hasConflictUniteOnRules(const vTuples& first, const vTuples& second)
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < (int)first.size(); ++i)
|
||||
{
|
||||
bool firstStar = first[i].first == "*";
|
||||
bool secondStar = second[i].first == "*";
|
||||
if (!firstStar && !secondStar)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ParallelDirective* operator+(const ParallelDirective &left, const ParallelDirective &right)
|
||||
{
|
||||
const ParallelDirective *first = &left;
|
||||
const ParallelDirective *second = &right;
|
||||
|
||||
ParallelDirective *result = NULL;
|
||||
checkNull(first, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
checkNull(second, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
bool condition = first->arrayRef == second->arrayRef;
|
||||
if (sharedMemoryParallelization)
|
||||
condition = !hasConflictUniteOnRules(first->on, second->on) && !hasConflictUniteOnRules(first->on2, second->on2);
|
||||
|
||||
if (condition)
|
||||
{
|
||||
if (first->on.size() != second->on.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
result = new ParallelDirective();
|
||||
|
||||
result->langType = first->langType;
|
||||
result->file = first->file;
|
||||
result->line = first->line;
|
||||
result->col = first->col;
|
||||
|
||||
result->arrayRef = first->arrayRef;
|
||||
result->arrayRef2 = first->arrayRef2;
|
||||
|
||||
result->parallel = vector<string>(first->parallel.size() + second->parallel.size());
|
||||
result->on = vector<pair<string, pair<int, int>>>(first->on.size());
|
||||
|
||||
for (int i = 0; i < (int)first->parallel.size(); ++i)
|
||||
result->parallel[i] = first->parallel[i];
|
||||
|
||||
for (int i = 0; i < (int)second->parallel.size(); ++i)
|
||||
result->parallel[i + first->parallel.size()] = second->parallel[i];
|
||||
|
||||
result->on = uniteOnRules(first->on, second->on);
|
||||
result->on2 = uniteOnRules(first->on2, second->on2);
|
||||
|
||||
uniteVectors(first->across, second->across, result->across);
|
||||
uniteVectors(first->shadowRenew, second->shadowRenew, result->shadowRenew);
|
||||
|
||||
uniteSets(first->privates, second->privates, result->privates);
|
||||
uniteSets(first->remoteAccess, second->remoteAccess, result->remoteAccess);
|
||||
|
||||
result->reduction = first->reduction;
|
||||
result->reductionLoc = first->reductionLoc;
|
||||
|
||||
uniteReduction(first->reduction, second->reduction, result->reduction);
|
||||
uniteReduction(first->reductionLoc, second->reductionLoc, result->reductionLoc);
|
||||
}
|
||||
else
|
||||
result = new ParallelDirective(left);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int findRule(const int alingDim, const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule, pair<int, pair<int, int>> &retVal)
|
||||
{
|
||||
for (int i = 0; i < rule.size(); ++i)
|
||||
{
|
||||
if (get<1>(rule[i]) == alingDim)
|
||||
{
|
||||
retVal = make_pair(alingDim, get<2>(rule[i]));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool isNonDistributedDim(const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForOn,
|
||||
const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForShadow,
|
||||
const int dimN,
|
||||
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
const vector<pair<string, pair<int, int>>> ¶llelOnRule)
|
||||
{
|
||||
if (ruleForShadow.size() <= dimN)
|
||||
return false;
|
||||
|
||||
if (get<0>(ruleForShadow[dimN]) == NULL)
|
||||
return true;
|
||||
|
||||
//check for distributed in declaration or in redistr. rules
|
||||
const tuple<DIST::Array*, int, pair<int, int>> &toCheck = ruleForShadow[dimN];
|
||||
const int dimInTepml = get<1>(toCheck);
|
||||
|
||||
for (auto &templ : distribution)
|
||||
{
|
||||
if (templ.first == get<0>(toCheck))
|
||||
{
|
||||
if (templ.second->distRule[dimInTepml] == NONE)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//check for distributed in loop
|
||||
if (dimInTepml >= 0 && dimInTepml < parallelOnRule.size())
|
||||
if (parallelOnRule[dimInTepml].first == "*")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>>
|
||||
getAlignRuleWithTemplate(DIST::Array *array, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
|
||||
DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays,
|
||||
const uint64_t regionId)
|
||||
{
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>> retVal;
|
||||
|
||||
set<DIST::Array*> realRefs;
|
||||
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
|
||||
|
||||
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> allRuleForShadow(realRefs.size());
|
||||
int idx = 0;
|
||||
for (auto &array : realRefs)
|
||||
reducedG.GetAlignRuleWithTemplate(array, allArrays, allRuleForShadow[idx++], regionId);
|
||||
|
||||
if (realRefs.size() == 1)
|
||||
retVal = allRuleForShadow[0];
|
||||
else
|
||||
{
|
||||
bool eq = isAllRulesEqual(allRuleForShadow);
|
||||
if (eq == false)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else
|
||||
retVal = allRuleForShadow[0];
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool needCorner(const DIST::Array* currArray, const vector<map<pair<int, int>, int>>& shiftsByAccess, const vector<vector<pair<int, int>>>& refsInLoop)
|
||||
{
|
||||
for (auto& access : refsInLoop)
|
||||
{
|
||||
int countOfShadows = 0;
|
||||
if (access.size() < currArray->GetDimSize())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < currArray->GetDimSize(); ++i)
|
||||
{
|
||||
const pair<int, int>& coef = access[i];
|
||||
auto it = shiftsByAccess[i].find(coef);
|
||||
if (it != shiftsByAccess[i].end())
|
||||
if (it->second != 0)
|
||||
countOfShadows++;
|
||||
}
|
||||
if (countOfShadows > 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline string calculateShifts(DIST::GraphCSR<int, double, attrType> &reducedG,
|
||||
const DIST::Arrays<int> &allArrays,
|
||||
DIST::Array *arrayRef, DIST::Array *calcForArray,
|
||||
pair<pair<string, string>, vector<pair<int, int>>> &coeffs,
|
||||
vector<pair<int, int>> &shifts,
|
||||
vector<map<pair<int, int>, int>> &shiftsByAccess,
|
||||
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
|
||||
const vector<pair<string, pair<int, int>>> baseOnRule,
|
||||
const vector<pair<string, pair<int, int>>> parallelOnRule,
|
||||
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps, const bool isAcross,
|
||||
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
const uint64_t regionId,
|
||||
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
|
||||
{
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForOn, ruleForShadow;
|
||||
|
||||
if (!sharedMemoryParallelization)
|
||||
{
|
||||
ruleForOn = getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
|
||||
ruleForShadow = getAlignRuleWithTemplate(calcForArray, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
|
||||
|
||||
}
|
||||
string out = "";
|
||||
// check for distributed and not mapped dims -> zero them out ('coeffs.second')
|
||||
set<DIST::Array*> refs;
|
||||
getRealArrayRefs(calcForArray, calcForArray, refs, arrayLinksByFuncCalls);
|
||||
|
||||
//TODO: need to correct errors
|
||||
/*if (!sharedMemoryParallelization)
|
||||
{
|
||||
for (auto& array : refs)
|
||||
{
|
||||
DIST::Array* tmpl = array->GetTemplateArray(regionId);
|
||||
checkNull(tmpl, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto align = array->GetLinksWithTemplate(regionId);
|
||||
|
||||
bool found = false;
|
||||
for (auto& t : distribution)
|
||||
{
|
||||
if (t.first == tmpl)
|
||||
{
|
||||
found = true;
|
||||
|
||||
for (int aDim = 0; aDim < align.size(); ++aDim)
|
||||
{
|
||||
int link = align[aDim];
|
||||
if (link != -1)
|
||||
{
|
||||
int tLink = link;
|
||||
if (!arrayRef->IsTemplate())
|
||||
{
|
||||
auto alignMain = arrayRef->GetLinksWithTemplate(regionId);
|
||||
for (int z = 0; z < alignMain.size(); ++z)
|
||||
if (alignMain[z] == tLink)
|
||||
tLink = z;
|
||||
}
|
||||
|
||||
if (t.second->distRule[link] == dist::BLOCK && baseOnRule[aDim].first == "*")
|
||||
{
|
||||
for (int z = 0; z < coeffs.second.size(); ++z)
|
||||
coeffs.second[z].first = coeffs.second[z].second = 0;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
}*/
|
||||
|
||||
const pair<vector<ArrayOp>, vector<bool>> *currReadOp = NULL;
|
||||
auto readIt = readOps.find(calcForArray);
|
||||
if (readIt != readOps.end())
|
||||
currReadOp = &(readIt->second);
|
||||
|
||||
if(!sharedMemoryParallelization)
|
||||
{
|
||||
findAndReplaceDimentions(ruleForOn, allArrays);
|
||||
findAndReplaceDimentions(ruleForShadow, allArrays);
|
||||
}
|
||||
|
||||
const int len = (int)coeffs.second.size();
|
||||
vector<pair<int, int>> shift(len);
|
||||
|
||||
bool allZero = true;
|
||||
for (int k = 0; k < len; ++k)
|
||||
{
|
||||
shiftsByAccess.push_back(map<pair<int, int>, int>());
|
||||
shift[k].first = shift[k].second = 0;
|
||||
|
||||
if (k != 0)
|
||||
out += ",";
|
||||
char buf[256];
|
||||
|
||||
// calculate correct shifts from readOp info
|
||||
if (currReadOp)
|
||||
{
|
||||
// no unrecognized read operations
|
||||
if (currReadOp->second[k] == false)
|
||||
{
|
||||
if (sharedMemoryParallelization)
|
||||
{
|
||||
for (auto& coefs : currReadOp->first[k].coefficients)
|
||||
{
|
||||
auto currAccess = coefs.first;
|
||||
|
||||
const int currShift = coefs.first.second;
|
||||
|
||||
auto itFound = shiftsByAccess[k].find(currAccess);
|
||||
if (itFound == shiftsByAccess[k].end())
|
||||
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
|
||||
}
|
||||
}
|
||||
else if (get<0>(ruleForShadow[k]) != NULL)
|
||||
{
|
||||
const pair<int, int> currRuleShadow = get<2>(ruleForShadow[k]);
|
||||
|
||||
pair<int, pair<int, int>> currRuleOn;
|
||||
int err = findRule(get<1>(ruleForShadow[k]), ruleForOn, currRuleOn);
|
||||
if (err == 0)
|
||||
{
|
||||
if (currRuleOn.first >= parallelOnRule.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const pair<int, int> loopRule = DIST::Fx(parallelOnRule[currRuleOn.first].second, currRuleOn.second);
|
||||
|
||||
if (loopRule.first != 0)
|
||||
{
|
||||
int minShift = 9999999;
|
||||
int maxShift = -9999999;
|
||||
|
||||
for (auto &coefs : currReadOp->first[k].coefficients)
|
||||
{
|
||||
auto currAccess = coefs.first;
|
||||
auto result = DIST::Fx(currAccess, currRuleShadow);
|
||||
|
||||
if (result.first == loopRule.first)
|
||||
{
|
||||
const int absShift = abs(result.second - loopRule.second);
|
||||
const int signShift = (result.second - loopRule.second) > 0 ? 1 : -1;
|
||||
|
||||
const int currShift = signShift * (absShift / currRuleShadow.first + ((absShift % currRuleShadow.first) != 0));
|
||||
|
||||
minShift = std::min(minShift, currShift);
|
||||
maxShift = std::max(maxShift, currShift);
|
||||
|
||||
auto itFound = shiftsByAccess[k].find(currAccess);
|
||||
if (itFound == shiftsByAccess[k].end())
|
||||
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
|
||||
}
|
||||
else // remote_access
|
||||
{
|
||||
auto it = remoteRegularReads.find(calcForArray);
|
||||
if (it == remoteRegularReads.end())
|
||||
it = remoteRegularReads.insert(it, make_pair(calcForArray, vector<ArrayOp>(calcForArray->GetDimSize())));
|
||||
it->second[k].coefficients.insert(coefs);
|
||||
}
|
||||
}
|
||||
|
||||
// inconsistent -> may be remote will add later...
|
||||
// or SINGLE position
|
||||
if (minShift == 9999999 && maxShift == -9999999)
|
||||
minShift = maxShift = 0;
|
||||
|
||||
if (minShift == maxShift)
|
||||
{
|
||||
if (minShift == 0)
|
||||
{
|
||||
if (parallelOnRule[currRuleOn.first].first != "SINGLE")
|
||||
{
|
||||
shift[k].first = -coeffs.second[k].first;
|
||||
shift[k].second = -coeffs.second[k].second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shift[k].first = -minShift;
|
||||
shift[k].second = minShift;
|
||||
|
||||
if (shift[k].first > 0 && shift[k].second < 0)
|
||||
shift[k].second = 0;
|
||||
else if (shift[k].first < 0 && shift[k].second > 0)
|
||||
shift[k].first = 0;
|
||||
|
||||
shift[k].first -= coeffs.second[k].first;
|
||||
shift[k].second -= coeffs.second[k].second;
|
||||
}
|
||||
}
|
||||
else if (currReadOp->first[k].coefficients.size() > 0)
|
||||
{
|
||||
if (minShift > 0 && maxShift > 0)
|
||||
{
|
||||
shift[k].first = 0;
|
||||
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
|
||||
}
|
||||
else if (minShift < 0 && maxShift < 0)
|
||||
{
|
||||
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
|
||||
shift[k].second = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
|
||||
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!sharedMemoryParallelization)
|
||||
{
|
||||
if (coeffs.second[k].first + shift[k].first < 0)
|
||||
shift[k].first = -coeffs.second[k].first;
|
||||
|
||||
if (coeffs.second[k].second + shift[k].second < 0)
|
||||
shift[k].second = -coeffs.second[k].second;
|
||||
|
||||
if (isAcross)
|
||||
{
|
||||
if (coeffs.second[k] == make_pair(0, 0))
|
||||
shift[k] = make_pair(0, 0);
|
||||
}
|
||||
else if (isNonDistributedDim(ruleForOn, ruleForShadow, k, distribution, parallelOnRule))
|
||||
{
|
||||
shift[k].first = -coeffs.second[k].first;
|
||||
shift[k].second = -coeffs.second[k].second;
|
||||
shiftsByAccess[k].clear();
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(buf, "%d:%d", coeffs.second[k].first + shift[k].first, coeffs.second[k].second + shift[k].second);
|
||||
shifts[k] = shift[k];
|
||||
|
||||
if (coeffs.second[k].first + shift[k].first != 0 || coeffs.second[k].second + shift[k].second != 0)
|
||||
allZero = false;
|
||||
out += buf;
|
||||
}
|
||||
|
||||
if (allZero)
|
||||
return "";
|
||||
else
|
||||
return out;
|
||||
}
|
||||
|
||||
string ParallelDirective::genBounds(pair<pair<string, string>, vector<pair<int, int>>> &shadowOp,
|
||||
vector<pair<int, int>> &shadowOpShift,
|
||||
DIST::GraphCSR<int, double, attrType> &reducedG,
|
||||
DIST::Arrays<int> &allArrays, DIST::Array* shadowArray,
|
||||
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
|
||||
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps,
|
||||
const bool isAcross,
|
||||
const uint64_t regionId,
|
||||
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
|
||||
set<DIST::Array*> &arraysInAcross,
|
||||
vector<map<pair<int, int>, int>> &shiftsByAccess,
|
||||
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls) const
|
||||
{
|
||||
checkNull(shadowArray, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto on_ext = on;
|
||||
|
||||
if(!sharedMemoryParallelization)
|
||||
{
|
||||
//replace to template align ::on
|
||||
if (arrayRef->IsTemplate() == false)
|
||||
{
|
||||
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForRef =
|
||||
getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
|
||||
findAndReplaceDimentions(ruleForRef, allArrays);
|
||||
|
||||
on_ext.clear();
|
||||
for (int i = 0; i < ruleForRef.size(); ++i)
|
||||
{
|
||||
if (get<0>(ruleForRef[i]))
|
||||
{
|
||||
on_ext.resize(get<0>(ruleForRef[i])->GetDimSize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (on_ext.size() == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
std::fill(on_ext.begin(), on_ext.end(), make_pair("*", make_pair(0, 0)));
|
||||
|
||||
for (int i = 0; i < ruleForRef.size(); ++i)
|
||||
if (get<0>(ruleForRef[i]))
|
||||
on_ext[get<1>(ruleForRef[i])] = on[i];
|
||||
}
|
||||
|
||||
//replace single dim to key word 'SINGLE'
|
||||
for (int i = 0; i < on_ext.size(); ++i)
|
||||
{
|
||||
if (on_ext[i].first != "*")
|
||||
{
|
||||
if (std::find(parallel.begin(), parallel.end(), on_ext[i].first) == parallel.end())
|
||||
on_ext[i].first = "SINGLE";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string ret = "";
|
||||
if (isAcross)
|
||||
{
|
||||
arraysInAcross.insert(shadowArray);
|
||||
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arraysInAcross.find(shadowArray) == arraysInAcross.end())
|
||||
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void genVariants(const int dimNum, vector<dist> &currDist, std::vector<DistrVariant> &currdist)
|
||||
{
|
||||
if (dimNum == 1)
|
||||
{
|
||||
DistrVariant var1(currDist);
|
||||
var1.distRule.push_back(dist::NONE);
|
||||
|
||||
DistrVariant var2(currDist);
|
||||
var2.distRule.push_back(dist::BLOCK);
|
||||
|
||||
currdist.push_back(var1);
|
||||
currdist.push_back(var2);
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<dist> next(currDist);
|
||||
next.push_back(dist::NONE);
|
||||
genVariants(dimNum - 1, next, currdist);
|
||||
next.back() = dist::BLOCK;
|
||||
genVariants(dimNum - 1, next, currdist);
|
||||
}
|
||||
}
|
||||
|
||||
void DataDirective::createDirstributionVariants(const vector<DIST::Array*> &arraysToDist)
|
||||
{
|
||||
for (int i = 0; i < arraysToDist.size(); ++i)
|
||||
{
|
||||
vector<DistrVariant> currdist;
|
||||
vector<dist> currDist;
|
||||
genVariants(arraysToDist[i]->GetDimSize(), currDist, currdist);
|
||||
|
||||
//deprecate by dims
|
||||
for (auto &variant : currdist)
|
||||
{
|
||||
for (int z = 0; z < arraysToDist[i]->GetDimSize(); ++z)
|
||||
if (arraysToDist[i]->IsDimDepracated(z) || !arraysToDist[i]->IsDimMapped(z))
|
||||
variant.distRule[z] = dist::NONE;
|
||||
}
|
||||
distrRules.push_back(make_pair(arraysToDist[i], currdist));
|
||||
}
|
||||
}
|
||||
|
||||
string DistrVariantBase::GenRuleBase(const vector<int> &newOrder) const
|
||||
{
|
||||
string retVal = "";
|
||||
|
||||
retVal += "(";
|
||||
for (int i = 0; i < distRule.size(); ++i)
|
||||
{
|
||||
if (newOrder.size() == 0)
|
||||
{
|
||||
if (distRule[i] == dist::NONE)
|
||||
retVal += "*";
|
||||
else if (distRule[i] == dist::BLOCK)
|
||||
retVal += "BLOCK";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (distRule[newOrder[i]] == dist::NONE)
|
||||
retVal += "*";
|
||||
else if (distRule[newOrder[i]] == dist::BLOCK)
|
||||
retVal += "BLOCK";
|
||||
}
|
||||
|
||||
if (i != distRule.size() - 1)
|
||||
retVal += ",";
|
||||
}
|
||||
retVal += ")";
|
||||
return retVal;
|
||||
}
|
||||
|
||||
vector<string> DataDirective::GenRule(const vector<int> &rules) const
|
||||
{
|
||||
vector<string> retVal;
|
||||
if (distrRules.size() < rules.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (rules[i] < distrRules[i].second.size())
|
||||
{
|
||||
string tmp = distrRules[i].first->GetShortName();
|
||||
tmp += distrRules[i].second[rules[i]].GenRuleBase(distrRules[i].first->GetNewTemplateDimsOrder());
|
||||
retVal.push_back(tmp);
|
||||
}
|
||||
else
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
vector<vector<dist>> DataDirective::GenRule(const vector<int> &rules, int) const
|
||||
{
|
||||
vector<vector<dist>> retVal;
|
||||
if (distrRules.size() < rules.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < rules.size(); ++i)
|
||||
{
|
||||
if (rules[i] < distrRules[i].second.size())
|
||||
retVal.push_back(distrRules[i].second[rules[i]].distRule);
|
||||
else
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
vector<string> DataDirective::GenAlignsRules() const
|
||||
{
|
||||
vector<string> retVal;
|
||||
for (int i = 0; i < alignRules.size(); ++i)
|
||||
retVal.push_back(alignRules[i].GenRuleBase());
|
||||
return retVal;
|
||||
}
|
||||
|
||||
string AlignRuleBase::GenRuleBase() const
|
||||
{
|
||||
string retVal = "";
|
||||
retVal += "ALIGN " + alignArray->GetShortName() + "(";
|
||||
for (int i = 0; i < alignRule.size(); ++i)
|
||||
{
|
||||
retVal += genStringExpr(alignNames[i], alignRule[i]);
|
||||
if (i != alignRule.size() - 1)
|
||||
retVal += ",";
|
||||
}
|
||||
|
||||
retVal += ") WITH " + alignWith->GetShortName() + "(";
|
||||
vector<string> alignEachDim(alignWith->GetDimSize());
|
||||
for (int i = 0; i < alignWith->GetDimSize(); ++i)
|
||||
alignEachDim[i] = "*";
|
||||
|
||||
for (int i = 0; i < alignRuleWith.size(); ++i)
|
||||
if (alignRuleWith[i].first != -1)
|
||||
alignEachDim[alignRuleWith[i].first] = genStringExpr(alignNames[i], alignRuleWith[i].second);
|
||||
|
||||
auto newOrder = alignWith->GetNewTemplateDimsOrder();
|
||||
if (newOrder.size() != 0)
|
||||
{
|
||||
vector<string> alignEachDimNew(alignEachDim);
|
||||
for (int z = 0; z < newOrder.size(); ++z)
|
||||
alignEachDim[z] = alignEachDimNew[newOrder[z]];
|
||||
}
|
||||
|
||||
for (int i = 0; i < alignWith->GetDimSize(); ++i)
|
||||
{
|
||||
retVal += alignEachDim[i];
|
||||
if (i != alignWith->GetDimSize() - 1)
|
||||
retVal += ",";
|
||||
}
|
||||
retVal += ")";
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
string AlignRuleBase::toString()
|
||||
{
|
||||
string retVal = "";
|
||||
|
||||
if (alignArray)
|
||||
retVal += "#" + std::to_string((long long)alignArray);
|
||||
else
|
||||
retVal += "#-1";
|
||||
|
||||
if (alignWith)
|
||||
retVal += "#" + std::to_string((long long)alignWith);
|
||||
else
|
||||
retVal += "#-1";
|
||||
|
||||
retVal += "#" + std::to_string(alignRule.size());
|
||||
for (int i = 0; i < alignRule.size(); ++i)
|
||||
retVal += "#" + std::to_string(alignRule[i].first) + "#" + std::to_string(alignRule[i].second);
|
||||
|
||||
retVal += "#" + std::to_string(alignRuleWith.size());
|
||||
for (int i = 0; i < alignRuleWith.size(); ++i)
|
||||
retVal += "#" + std::to_string(alignRuleWith[i].first)
|
||||
+ "#" + std::to_string(alignRuleWith[i].second.first)
|
||||
+ "#" + std::to_string(alignRuleWith[i].second.second);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
pair<string, string> convertDigitToPositive(const int digit)
|
||||
{
|
||||
char buf[16];
|
||||
string sign = " + ";
|
||||
if (digit < 0)
|
||||
{
|
||||
sign = " - ";
|
||||
int val = -digit;
|
||||
sprintf(buf, "%d", val);
|
||||
}
|
||||
else
|
||||
sprintf(buf, "%d", digit);
|
||||
|
||||
return make_pair(sign, buf);
|
||||
}
|
||||
|
||||
string genStringExpr(const string &letter, const pair<int, int> expr)
|
||||
{
|
||||
string retVal = "";
|
||||
if (expr.first == 0 && expr.second == 0)
|
||||
retVal = "*";
|
||||
else if (expr.second == 0)
|
||||
{
|
||||
if (expr.first == 1)
|
||||
retVal = letter;
|
||||
else
|
||||
{
|
||||
pair<string, string> digit2 = convertDigitToPositive(expr.first);
|
||||
if (digit2.first == " - ")
|
||||
digit2.second = "(-" + digit2.second + ")";
|
||||
retVal = digit2.second + string(" * ") + letter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pair<string, string> digit1 = convertDigitToPositive(expr.second);
|
||||
if (expr.first == 1)
|
||||
retVal = letter + digit1.first + digit1.second;
|
||||
else
|
||||
{
|
||||
pair<string, string> digit2 = convertDigitToPositive(expr.first);
|
||||
if (digit2.first == " - ")
|
||||
digit2.second = "(-" + digit2.second + ")";
|
||||
retVal = digit2.second + string(" * ") + letter + digit1.first + digit1.second;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
const std::vector<std::string> AlignRuleBase::alignNames = { "iEX1", "iEX2", "iEX3", "iEX4", "iEX5", "iEX6", "iEX7" };
|
||||
70
src/Distribution/DvmhDirectiveBase.h
Normal file
70
src/Distribution/DvmhDirectiveBase.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
typedef enum lang : int { LANG_C, LANG_F } language;
|
||||
typedef enum dist : int { BLOCK, NONE } distType;
|
||||
typedef std::pair<std::pair<int, int>, std::pair<int, int>> attrType;
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class Array;
|
||||
}
|
||||
namespace DIST = Distribution;
|
||||
|
||||
struct Directive
|
||||
{
|
||||
lang langType;
|
||||
std::string file;
|
||||
int line;
|
||||
int col;
|
||||
|
||||
Directive ()
|
||||
{
|
||||
#if __SPF
|
||||
langType = LANG_F;
|
||||
#else
|
||||
langType = LANG_C;
|
||||
#endif
|
||||
file = "";
|
||||
line = 0;
|
||||
col = 0;
|
||||
}
|
||||
|
||||
Directive(const Directive &dir)
|
||||
{
|
||||
langType = dir.langType;
|
||||
file = dir.file;
|
||||
line = dir.line;
|
||||
col = dir.col;
|
||||
}
|
||||
};
|
||||
|
||||
struct AlignRuleBase
|
||||
{
|
||||
public:
|
||||
static const std::vector<std::string> alignNames;
|
||||
|
||||
public:
|
||||
std::string GenRuleBase() const;
|
||||
std::string toString();
|
||||
|
||||
public:
|
||||
DIST::Array *alignArray;
|
||||
DIST::Array *alignWith;
|
||||
std::vector<std::pair<int, int>> alignRule;
|
||||
std::vector<std::pair<int, std::pair<int, int>>> alignRuleWith;
|
||||
};
|
||||
|
||||
struct DistrVariantBase
|
||||
{
|
||||
public:
|
||||
std::vector<dist> distRule;
|
||||
|
||||
public:
|
||||
DistrVariantBase(const std::vector<dist> &distRule) : distRule(distRule) { }
|
||||
std::string GenRuleBase(const std::vector<int> &newOrder) const;
|
||||
};
|
||||
|
||||
bool needCorner(const DIST::Array* currArray, const std::vector<std::map<std::pair<int, int>, int>>& shiftsByAccess, const std::vector<std::vector<std::pair<int, int>>>& refsInLoop);
|
||||
12
src/Distribution/DvmhDirective_func.h
Normal file
12
src/Distribution/DvmhDirective_func.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "dvm.h"
|
||||
#include "../Utils/types.h"
|
||||
|
||||
SgExpression* createAndSetNext(const int side, const int variant, SgExpression *p);
|
||||
std::vector<SgExpression*> genSubscripts(const std::vector<std::pair<int, int>> &shadowRenew, const std::vector<std::pair<int, int>> &shadowRenewShifts);
|
||||
std::pair<SgExpression*, SgExpression*> genShadowSpec(SgFile *file, const std::pair<std::string, const std::vector<std::pair<int, int>>> &shadowSpecs);
|
||||
void correctShadowSpec(SgExpression *spec, const std::vector<std::pair<int, int>> &shadowSpecs);
|
||||
2302
src/Distribution/GraphCSR.cpp
Normal file
2302
src/Distribution/GraphCSR.cpp
Normal file
File diff suppressed because it is too large
Load Diff
171
src/Distribution/GraphCSR.h
Normal file
171
src/Distribution/GraphCSR.h
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
#include "../Utils/RationalNum.h"
|
||||
|
||||
typedef enum links { RR_link, WR_link, WW_link } LinkType;
|
||||
|
||||
#define MAX_LOOP_DIM 8
|
||||
#define MAX_CHAIN_LEN 8
|
||||
|
||||
namespace Distribution
|
||||
{
|
||||
class Array;
|
||||
template<typename vType> class Arrays;
|
||||
template<typename vType, typename wType, typename attrType> class Cycle;
|
||||
|
||||
template<typename vType, typename wType, typename attrType>
|
||||
class GraphCSR
|
||||
{
|
||||
private:
|
||||
vType numVerts;
|
||||
vType numEdges;
|
||||
vType lastNumOfV;
|
||||
|
||||
std::vector<vType> neighbors;
|
||||
std::vector<vType> edges;
|
||||
std::vector<wType> weights;
|
||||
std::vector<uint8_t> linkType;
|
||||
std::vector<attrType> attributes;
|
||||
std::vector<vType> localIdx;
|
||||
std::vector<vType> globalIdx;
|
||||
|
||||
//for finding
|
||||
std::vector<vType> color;
|
||||
vType *activeV;
|
||||
vType *activeE;
|
||||
std::pair<wType, attrType> *activeArcs;
|
||||
uint64_t usedMem;
|
||||
std::vector<std::pair<int, int>> treesQuality;
|
||||
|
||||
int activeCounter;
|
||||
vType findFrom;
|
||||
bool hardLinksWasUp;
|
||||
|
||||
int maxChainLen;
|
||||
int maxLoopDim;
|
||||
uint64_t maxAvailMemory;
|
||||
|
||||
std::map<vType, std::map<vType, std::tuple<int, Array*, std::pair<RationalNum, RationalNum>>>> cacheLinks;
|
||||
int countRequestsToAdd, countMissToAdd;
|
||||
private:
|
||||
GraphCSR(const std::vector<vType> &neighbors, const std::vector<vType> &edges,
|
||||
const std::vector<wType> &weights, const std::vector<vType> &localIdx,
|
||||
const std::vector<vType> &globalIdx, const std::vector<attrType> &attributes,
|
||||
const std::vector<uint8_t> &linkType, const bool hardLinksWasUp) :
|
||||
neighbors(neighbors), edges(edges), weights(weights), localIdx(localIdx),
|
||||
globalIdx(globalIdx), attributes(attributes), linkType(linkType), hardLinksWasUp(hardLinksWasUp)
|
||||
{
|
||||
numVerts = (int)neighbors.size() - 1;
|
||||
numEdges = (int)edges.size();
|
||||
}
|
||||
|
||||
vType GetLocalVNum(const vType &V, bool &ifNew);
|
||||
void AddEdgeToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const bool &ifNew, const uint8_t linkType);
|
||||
void IncreaseWeight(const int &idx, const int &idxRev, const wType &W);
|
||||
int CheckExist(const vType &V1, const vType &V2, const attrType &attr, const bool &ifNew, const uint8_t &linkType);
|
||||
|
||||
//old algorithm without sort in the fly
|
||||
//TODO: need to update
|
||||
void FindLoop(std::vector<Cycle<vType, wType, attrType>> &cycles, const vType V, const vType VPrev);
|
||||
void FindLoop(std::vector<std::map<std::vector<unsigned>, Cycle<vType, wType, attrType>>> &cycles, const vType V, const vType VPrev, const std::vector<vType> &numbers);
|
||||
void RemoveDuplicates(std::vector<Cycle<vType, wType, attrType>> &cycles);
|
||||
bool findLink(const vType v1, std::pair<int, int> &inGraphAttr1, const vType v2, std::pair<int, int> &inGraphAttr2);
|
||||
std::pair<RationalNum, RationalNum> findLinkWithTempate2(const vType v1, int &templV, Array *&templ, const Arrays<vType> &allArrays, std::set<vType> wasDone);
|
||||
int findDimNumLink(const vType v, const Array *to, const Arrays<vType> &allArrays, std::set<vType> &wasDone) const;
|
||||
bool checkFirstCoefOfNode(vType node);
|
||||
bool getOptimalBoundsForNode(vType nodeFrom, vType nodeTo, int &needBound, std::pair<int, int> &bounds);
|
||||
bool hasLinkWithTempate(const vType root, const Arrays<vType> &allArrays, bool, int newValue = 0);
|
||||
public:
|
||||
GraphCSR()
|
||||
{
|
||||
ClearGraphCSR();
|
||||
}
|
||||
|
||||
GraphCSR(const GraphCSR &G) : GraphCSR(G.neighbors, G.edges, G.weights, G.localIdx, G.globalIdx, G.attributes, G.linkType, G.hardLinksWasUp)
|
||||
{
|
||||
this->lastNumOfV = G.lastNumOfV;
|
||||
this->maxLoopDim = G.maxLoopDim;
|
||||
this->maxChainLen = G.maxChainLen;
|
||||
this->maxAvailMemory = G.maxAvailMemory;
|
||||
this->countRequestsToAdd = G.countRequestsToAdd;
|
||||
this->countMissToAdd = G.countMissToAdd;
|
||||
this->treesQuality = G.treesQuality;
|
||||
}
|
||||
|
||||
void cleanCacheLinks() { cacheLinks.clear(); }
|
||||
|
||||
void ClearGraphCSR()
|
||||
{
|
||||
lastNumOfV = numVerts = numEdges = 0;
|
||||
hardLinksWasUp = false;
|
||||
neighbors.resize(0);
|
||||
edges.resize(0);
|
||||
weights.resize(0);
|
||||
linkType.resize(0);
|
||||
localIdx.resize(0);
|
||||
globalIdx.resize(0);
|
||||
attributes.resize(0);
|
||||
treesQuality.resize(0);
|
||||
|
||||
maxLoopDim = MAX_LOOP_DIM;
|
||||
maxChainLen = MAX_CHAIN_LEN;
|
||||
maxAvailMemory = 0;
|
||||
countRequestsToAdd = 0;
|
||||
countMissToAdd = 0;
|
||||
}
|
||||
|
||||
std::set<vType> FindTrees(std::vector<vType> &inTree, std::vector<std::vector<vType>> &vertByTrees);
|
||||
bool SaveGraphToFile(FILE *file);
|
||||
bool LoadGraphFromFile(FILE *file);
|
||||
int AddToGraph(const vType &V1, const vType &V2, const wType &W, const attrType &attr, const uint8_t linkType);
|
||||
void GetAllSimpleLoops(std::vector<std::vector<Cycle<vType, wType, attrType>>> &cycles, bool needPrint, bool useSavedQ);
|
||||
int SortLoopsBySize(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
|
||||
int SortLoopsByWeight(std::vector<Cycle<vType, wType, attrType>> &cycles, bool needPrint);
|
||||
int GetConflictCycles(const std::vector<Cycle<vType, wType, attrType>> &cycles, const Arrays<vType> &allArrays, std::vector<std::pair<int, int>> &indexOfConflict, bool needPrint);
|
||||
void RemoveMultipleArcsByWeights();
|
||||
void RemoveMultipleArcsOptimal();
|
||||
void RemoveVerticesByWeight();
|
||||
int CreateGraphWiz(const char *fileName, const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays, const bool onlyTree);
|
||||
void RemovedEdges(const std::vector<std::tuple<vType, vType, attrType>> &toDelArcs, const Arrays<vType> &allArrays);
|
||||
void HighlightLinks();
|
||||
|
||||
int GetAlignRuleForArray(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::vector<std::tuple<Array*, vType, attrType>>> &assignedArrays);
|
||||
int GetAlignRuleWithTemplate(Array *inputArray, const Arrays<vType> &allArrays, std::vector<std::tuple<Array*, vType, std::pair<int, int>>> &rules, const uint64_t regionId);
|
||||
void FindLinksBetweenArrays(const Arrays<vType> &allArrays, const Array *from, const Array *to, std::vector<int> &links) const;
|
||||
void FindLinkWithMaxDim(const vType from, const Arrays<vType> &allArrays, std::pair<Array*, int> &result, std::set<int> &wasDone);
|
||||
int FindAllArraysTrees(std::map<Array*, int> &trees, const Arrays<vType> &allArrays);
|
||||
|
||||
vType GetNumberOfV() const { return numVerts; }
|
||||
vType GetNumberOfE() const { return numEdges; }
|
||||
|
||||
void SetMaxLoopDim(const int newMaxLoopDim) { maxLoopDim = newMaxLoopDim; }
|
||||
void SetMaxChainLen(const int newMaxChainLen) { maxChainLen = newMaxChainLen; }
|
||||
int GetMaxLoopDim() const { return maxLoopDim; }
|
||||
int GetMaxChainLen() const { return maxChainLen; }
|
||||
void SetMaxAvailMemory(const uint64_t memSize) { maxAvailMemory = memSize; }
|
||||
void ChangeQuality(const int newMaxLoopDim, const int newMaxChainLen) { SetMaxLoopDim(newMaxLoopDim); SetMaxChainLen(newMaxChainLen); }
|
||||
int getCountOfReq() const { return countRequestsToAdd; }
|
||||
int getCountOfMiss() const { return countMissToAdd; }
|
||||
|
||||
std::vector<attrType> GetAllAttributes(const int vert) const;
|
||||
int CountOfConnected(const vType startV) const;
|
||||
int CountOfConnectedForArray(const vType startV) const;
|
||||
std::vector<std::tuple<vType, vType, attrType>> CreateMaximumSpanningTree();
|
||||
std::pair<int, int> MakeConnected(const vType startV, std::vector<unsigned char> &inSet) const;
|
||||
double CalculateSumOfWeights() const
|
||||
{
|
||||
double ret = 0;
|
||||
for (int z = 0; z < weights.size(); ++z)
|
||||
ret += weights[z] / 2.0;
|
||||
return ret;
|
||||
}
|
||||
void RemoveAllEdgesFromGraph(const std::map<Array*, std::vector<std::pair<int, int>>>& toDel, const Arrays<vType>& allArrays);
|
||||
};
|
||||
|
||||
std::pair<int, int> Fx(const std::pair<int, int> &x, const std::pair<int, int> &F);
|
||||
}
|
||||
Reference in New Issue
Block a user