finalyze moving

This commit is contained in:
2025-03-12 14:28:04 +03:00
parent f840006398
commit 033bbce220
774 changed files with 0 additions and 0 deletions

236
src/Distribution/Array.cpp Normal file
View 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
View 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 &copy)
{
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> &regions, 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 &reg : regions)
containsInRegions.insert(reg);
}
Array(const Array &copy)
{
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 &reg : 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 &regName) { 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

View 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
View 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 &copy)
{
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

View 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;
}

View 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
View 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> &paramArc, 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> &paramArc, 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
View 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> &paramArc, const unsigned info);
void AddArc(const vType V1, const vType V2, const std::pair<wType, attrType> &paramArc, 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;
}
};
}

View 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

View 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);
}

File diff suppressed because it is too large Load Diff

View 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 &copyFrom) : 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);

View 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>>> &parallelOnRule)
{
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" };

View 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);

View 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);

File diff suppressed because it is too large Load Diff

171
src/Distribution/GraphCSR.h Normal file
View 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);
}