modernize ParallelTopology

This commit is contained in:
Joachim Schöberl 2020-08-29 09:36:46 +02:00
parent fcee13be59
commit f8dd4be8d6
4 changed files with 164 additions and 75 deletions

View File

@ -54,7 +54,7 @@ namespace ngcore
NGCORE_API size_t * TablePrefixSum64 (FlatArray<size_t> entrysize)
{ return TablePrefixSum2 (entrysize); }
/*
BaseDynamicTable :: BaseDynamicTable (int size)
: data(size)
{
@ -88,7 +88,6 @@ namespace ngcore
}
}
BaseDynamicTable :: ~BaseDynamicTable ()
{
if (oneblock)
@ -112,7 +111,7 @@ namespace ngcore
}
}
void BaseDynamicTable :: IncSize (int i, int elsize)
void BaseDynamicTable :: IncSize (IndexType i, int elsize)
{
if (i < 0 || i >= data.Size())
{
@ -135,7 +134,7 @@ namespace ngcore
line.size++;
}
void BaseDynamicTable :: DecSize (int i)
void BaseDynamicTable :: DecSize (IndexType i)
{
if (i < 0 || i >= data.Size())
{
@ -153,6 +152,7 @@ namespace ngcore
line.size--;
}
*/
void FilteredTableCreator::Add (size_t blocknr, int data)
{

View File

@ -349,10 +349,12 @@ public:
};
/// Base class to generic DynamicTable.
/// Base class to generic DynamicTable.
template <class IndexType = size_t>
class BaseDynamicTable
{
protected:
static constexpr IndexType BASE = IndexBASE<IndexType>();
///
struct linestruct
@ -366,24 +368,106 @@ public:
};
///
Array<linestruct> data;
Array<linestruct, IndexType> data;
///
char * oneblock;
public:
///
NGCORE_API BaseDynamicTable (int size);
BaseDynamicTable (int size)
: data(size)
{
for (auto & d : data)
{
d.maxsize = 0;
d.size = 0;
d.col = nullptr;
}
oneblock = nullptr;
}
///
NGCORE_API BaseDynamicTable (const Array<int> & entrysizes, int elemsize);
BaseDynamicTable (const Array<int, IndexType> & entrysizes, int elemsize)
: data(entrysizes.Size())
{
int cnt = 0;
int n = entrysizes.Size();
for (auto es : entrysizes)
cnt += es;
oneblock = new char[elemsize * cnt];
cnt = 0;
for (auto i : Range(data))
{
data[i].maxsize = entrysizes[i];
data[i].size = 0;
data[i].col = &oneblock[elemsize * cnt];
cnt += entrysizes[i];
}
}
///
NGCORE_API ~BaseDynamicTable ();
~BaseDynamicTable ()
{
if (oneblock)
delete [] oneblock;
else
for (auto & d : data)
delete [] static_cast<char*> (d.col);
}
/// Changes Size of table to size, deletes data
NGCORE_API void SetSize (int size);
///
NGCORE_API void IncSize (int i, int elsize);
void SetSize (int size)
{
for (auto & d : data)
delete [] static_cast<char*> (d.col);
NGCORE_API void DecSize (int i);
data.SetSize(size);
for (auto & d : data)
{
d.maxsize = 0;
d.size = 0;
d.col = NULL;
}
}
///
void IncSize (IndexType i, int elsize)
{
NETGEN_CHECK_RANGE(i,BASE,data.Size()+BASE);
linestruct & line = data[i];
if (line.size == line.maxsize)
{
void * p = new char [(2*line.maxsize+5) * elsize];
memcpy (p, line.col, line.maxsize * elsize);
delete [] static_cast<char*> (line.col);
line.col = p;
line.maxsize = 2*line.maxsize+5;
}
line.size++;
}
void DecSize (IndexType i)
{
NETGEN_CHECK_RANGE(i,BASE,data.Size()+BASE);
/*
if (i < 0 || i >= data.Size())
{
std::cerr << "BaseDynamicTable::Dec: Out of range" << std::endl;
return;
}
*/
linestruct & line = data[i];
if (line.size == 0)
throw Exception ("BaseDynamicTable::Dec: EntrySize < 0");
line.size--;
}
};
@ -394,17 +478,19 @@ public:
A DynamicTable contains entries of variable size. Entry sizes can
be increased dynamically.
*/
template <class T>
class DynamicTable : public BaseDynamicTable
template <class T, class IndexType = size_t>
class DynamicTable : public BaseDynamicTable<IndexType>
{
using BaseDynamicTable<IndexType>::data;
using BaseDynamicTable<IndexType>::oneblock;
public:
/// Creates table of size size
DynamicTable (int size = 0)
: BaseDynamicTable (size) { ; }
: BaseDynamicTable<IndexType> (size) { }
/// Creates table with a priori fixed entry sizes.
DynamicTable (const Array<int> & entrysizes)
: BaseDynamicTable (entrysizes, sizeof(T)) { ; }
DynamicTable (const Array<int, IndexType> & entrysizes)
: BaseDynamicTable<IndexType> (entrysizes, sizeof(T)) { }
DynamicTable & operator= (DynamicTable && tab2)
{
@ -414,17 +500,17 @@ public:
}
/// Inserts element acont into row i. Does not test if already used.
void Add (int i, const T & acont)
void Add (IndexType i, const T & acont)
{
if (data[i].size == data[i].maxsize)
IncSize (i, sizeof (T));
this->IncSize (i, sizeof (T));
else
data[i].size++;
static_cast<T*> (data[i].col) [data[i].size-1] = acont;
}
/// Inserts element acont into row i, iff not yet exists.
void AddUnique (int i, const T & cont)
void AddUnique (IndexType i, const T & cont)
{
int es = EntrySize (i);
int * line = const_cast<int*> (GetLine (i));
@ -436,25 +522,25 @@ public:
/// Inserts element acont into row i. Does not test if already used.
void AddEmpty (int i)
void AddEmpty (IndexType i)
{
IncSize (i, sizeof (T));
}
/** Set the nr-th element in the i-th row to acont.
Does not check for overflow. */
void Set (int i, int nr, const T & acont)
void Set (IndexType i, int nr, const T & acont)
{ static_cast<T*> (data[i].col)[nr] = acont; }
/** Returns the nr-th element in the i-th row.
Does not check for overflow. */
const T & Get (int i, int nr) const
const T & Get (IndexType i, int nr) const
{ return static_cast<T*> (data[i].col)[nr]; }
/** Returns pointer to the first element in row i. */
const T * GetLine (int i) const
const T * GetLine (IndexType i) const
{ return static_cast<T*> (data[i].col); }
@ -463,15 +549,15 @@ public:
{ return data.Size(); }
/// Returns size of the i-th row.
int EntrySize (int i) const
int EntrySize (IndexType i) const
{ return data[i].size; }
///
void DecEntrySize (int i)
void DecEntrySize (IndexType i)
{ DecSize(i); }
/// Access entry i
FlatArray<T> operator[] (int i)
FlatArray<T> operator[] (IndexType i)
{ return FlatArray<T> (data[i].size, static_cast<T*> (data[i].col)); }
/*
@ -480,7 +566,7 @@ public:
ConstFlatArray operator[] (int i) const
{ return FlatArray<T> (data[i].size, static_cast<T*> (data[i].col)); }
*/
FlatArray<T> operator[] (int i) const
FlatArray<T> operator[] (IndexType i) const
{ return FlatArray<T> (data[i].size, static_cast<T*> (data[i].col)); }
};

View File

@ -51,8 +51,8 @@ namespace netgen
if ( mesh.GetCommunicator().Size() == 1 ) return;
int ned = mesh.GetTopology().GetNEdges();
int nfa = mesh.GetTopology().GetNFaces();
size_t ned = mesh.GetTopology().GetNEdges();
size_t nfa = mesh.GetTopology().GetNFaces();
if (glob_edge.Size() != ned)
{
@ -89,27 +89,28 @@ namespace netgen
*testout << "enumerate globally, loc2distvert.size = " << loc2distvert.Size()
<< ", glob_vert.size = " << glob_vert.Size() << endl;
// *testout << "old glob_vert = " << endl << glob_vert << endl;
if (rank == 0)
nv = 0;
IntRange newvr(oldnv, nv); // new vertex range
// IntRange newvr(oldnv, nv); // new vertex range
auto new_pir = Range(PointIndex(oldnv+PointIndex::BASE),
PointIndex(nv+PointIndex::BASE));
glob_vert.SetSize (nv);
glob_vert.Range(newvr) = -1;
glob_vert.Range(oldnv, nv) = -1;
int num_master_points = 0;
for (auto i : newvr)
for (auto pi : new_pir)
{
auto dps = GetDistantPNums(i);
auto dps = GetDistantProcs(pi);
// check sorted:
for (int j = 0; j+1 < dps.Size(); j++)
if (dps[j+1] < dps[j]) cout << "wrong sort" << endl;
if (dps.Size() == 0 || dps[0] > comm.Rank())
glob_vert[i] = num_master_points++;
L2G(pi) = num_master_points++;
}
*testout << "nummaster = " << num_master_points << endl;
@ -120,7 +121,7 @@ namespace netgen
if (comm.AllReduce (oldnv, MPI_SUM) == 0)
max_oldv = PointIndex::BASE-1;
size_t num_glob_points = max_oldv+1; // PointIndex::BASE;
size_t num_glob_points = max_oldv+1;
for (int i = 0; i < comm.Size(); i++)
{
int cur = first_master_point[i];
@ -128,9 +129,9 @@ namespace netgen
num_glob_points += cur;
}
for (auto i : newvr)
if (glob_vert[i] != -1)
glob_vert[i] += first_master_point[comm.Rank()];
for (auto pi : new_pir)
if (L2G(pi) != -1)
L2G(pi) += first_master_point[comm.Rank()];
// ScatterDofData (global_nums);
@ -139,12 +140,12 @@ namespace netgen
nrecv = 0;
/** Count send/recv size **/
for (auto i : newvr)
for (auto pi : new_pir)
{
auto dps = GetDistantPNums(i);
auto dps = GetDistantProcs(pi);
if (!dps.Size()) continue;
if (rank < dps[0])
for(auto p:dps)
for (auto p : dps)
nsend[p]++;
else
nrecv[dps[0]]++;
@ -155,13 +156,11 @@ namespace netgen
/** Fill send_data **/
nsend = 0;
for (auto i : newvr)
{
auto dps = GetDistantPNums(i);
if (dps.Size() && rank < dps[0])
for(auto p : dps)
send_data[p][nsend[p]++] = glob_vert[i];
}
for (auto pi : new_pir)
if (auto dps = GetDistantProcs(pi); dps.Size())
if (rank < dps[0])
for (auto p : dps)
send_data[p][nsend[p]++] = L2G(pi);
Array<MPI_Request> requests;
for (int i = 0; i < comm.Size(); i++)
@ -177,19 +176,21 @@ namespace netgen
Array<int> cnt(comm.Size());
cnt = 0;
for (auto i : newvr)
/*
for (auto pi : new_pir)
{
auto dps = GetDistantPNums(i);
auto dps = GetDistantProcs(pi);
if (dps.Size() > 0 && dps[0] < comm.Rank())
{
int master = comm.Size();
for (int j = 0; j < dps.Size(); j++)
master = min (master, dps[j]);
if (master != dps[0])
cout << "master not the first one !" << endl;
glob_vert[i] = recv_data[master][cnt[master]++];
int master = dps[0];
L2G(pi) = recv_data[master][cnt[master]++];
}
}
*/
for (auto pi : new_pir)
if (auto dps = GetDistantProcs(pi); dps.Size())
if (int master = dps[0]; master < comm.Rank())
L2G(pi) = recv_data[master][cnt[master]++];
/*
if (PointIndex::BASE==1)
@ -208,13 +209,11 @@ namespace netgen
Array<int> index0(glob_vert.Size());
for (int pi : Range(index0))
index0[pi] = pi;
QuickSortI (FlatArray<int> (glob_vert), index0);
QuickSortI (glob_vert, index0);
comm.Barrier();
for (int i = 0; i+1 < glob_vert.Size(); i++)
for (size_t i = 0; i+1 < glob_vert.Size(); i++)
if (glob_vert[index0[i]] > glob_vert[index0[i+1]])
cout << "wrong ordering" << endl;
comm.Barrier();
if (rank != 0)
{
@ -272,7 +271,7 @@ namespace netgen
// *testout << "l " << i << " globi "<< glob_vert[i] << " dist = " << loc2distvert[i] << endl;
}
for (int i = 0; i+1 < glob_vert.Size(); i++)
for (size_t i = 0; i+1 < glob_vert.Size(); i++)
if (glob_vert[i] > glob_vert[i+1])
cout << "wrong ordering of globvert" << endl;
@ -536,11 +535,11 @@ namespace netgen
// build exchange vertices
cnt_send = 0;
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
cnt_send[dist-1]++;
TABLE<int> dest2vert(cnt_send);
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
dest2vert.Add (dist-1, pi);
for (PointIndex pi = PointIndex::BASE; pi < newnv+PointIndex::BASE; pi++)
@ -687,11 +686,11 @@ namespace netgen
// build exchange vertices
cnt_send = 0;
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
cnt_send[dist-1]++;
TABLE<int> dest2vert(cnt_send);
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
dest2vert.Add (dist-1, pi);
MPI_Group_free(&MPI_LocalGroup);
@ -916,11 +915,11 @@ namespace netgen
// build exchange vertices
cnt_send = 0;
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
cnt_send[dist-1]++;
TABLE<int> dest2vert(cnt_send);
for (PointIndex pi : mesh.Points().Range())
for (int dist : GetDistantPNums(pi-PointIndex::BASE))
for (int dist : GetDistantProcs(pi))
dest2vert.Add (dist-1, pi);
// exchange edges

View File

@ -123,6 +123,10 @@ namespace netgen
FlatArray<int> GetDistantEdgeNums (int locnum) const { return loc2distedge[locnum]; }
FlatArray<int> GetDistantProcs (PointIndex pi) const { return loc2distvert[pi-PointIndex::BASE]; }
auto & L2G (PointIndex pi) { return glob_vert[pi-PointIndex::BASE]; }
auto L2G (PointIndex pi) const { return glob_vert[pi-PointIndex::BASE]; }
[[deprecated("Use GetDistantProcs(..).Contains instead!")]]
bool IsExchangeVert (int dest, int vnum) const
{