STYLE: adjust globalIndex/CompactListList overflow reporting

- report location with previous good offset and the new count that
  would cause overflow. Simpler to report and the (very long) list
  of input sizes is not particularly useful for diagnostics either.

ENH: add globalIndex comparison operators

- for outputting lists of globalIndex
This commit is contained in:
Mark Olesen 2023-11-18 11:48:08 +01:00
parent 5e0cafa637
commit ef201ecfea
6 changed files with 134 additions and 63 deletions

View File

@ -35,16 +35,25 @@ template<class T>
void Foam::CompactListList<T>::reportOverflowAndExit void Foam::CompactListList<T>::reportOverflowAndExit
( (
const label idx, const label idx,
const labelUList& localLens const label prevOffset,
const label count
) )
{ {
if (idx < 0)
{
// No overflow tagged
return;
}
FatalErrorInFunction FatalErrorInFunction
<< "Overflow : sum of sizes exceeds labelMax (" << "Overflow : sum of sizes exceeds labelMax ("
<< labelMax << ") after index " << idx; << labelMax << ") after index " << idx;
if (!localLens.empty()) if (prevOffset >= 0 && count >= 0)
{ {
FatalError << " of " << flatOutput(localLens); FatalError
<< " while trying to add (" << count
<< ") to offset (" << prevOffset << ")";
} }
FatalError FatalError
@ -76,12 +85,14 @@ Foam::CompactListList<T> Foam::CompactListList<T>::pack_impl
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = lists[i].size();
newOffsets[i] = total; newOffsets[i] = total;
total += lists[i].size(); total += count;
if (checkOverflow && total < newOffsets[i]) if (checkOverflow && total < newOffsets[i])
{ {
reportOverflowAndExit(i); reportOverflowAndExit(i, newOffsets[i], count);
} }
} }
newOffsets[len] = total; newOffsets[len] = total;
@ -162,12 +173,14 @@ Foam::label Foam::CompactListList<T>::resize_offsets
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = listSizes[i];
offsets_[i] = total; offsets_[i] = total;
total += listSizes[i]; total += count;
if (checkOverflow && total < offsets_[i]) if (checkOverflow && total < offsets_[i])
{ {
reportOverflowAndExit(i, listSizes); reportOverflowAndExit(i, offsets_[i], count);
} }
} }
@ -229,8 +242,8 @@ Foam::label Foam::CompactListList<T>::maxNonLocalSize(const label rowi) const
{ {
if (i != rowi) if (i != rowi)
{ {
const label localLen = (offsets_[i+1] - offsets_[i]); const label count = (offsets_[i+1] - offsets_[i]);
maxLen = max(maxLen, localLen); maxLen = max(maxLen, count);
} }
} }

View File

@ -82,11 +82,12 @@ class CompactListList
// Private Member Functions // Private Member Functions
//- Report overflow at specified index //- Report overflow at specified (non-negative) index
static void reportOverflowAndExit static void reportOverflowAndExit
( (
const label idx, const label idx,
const labelUList& listSizes = labelUList::null() const label prevOffset = -1, // The last valid offset value
const label count = 0 // The count to add to prevOffset
); );
//- Construct by packing together the list of lists //- Construct by packing together the list of lists

View File

@ -34,16 +34,25 @@ License
void Foam::globalIndex::reportOverflowAndExit void Foam::globalIndex::reportOverflowAndExit
( (
const label idx, const label idx,
const labelUList& localLens const label prevOffset,
const label count
) )
{ {
if (idx < 0)
{
// No overflow tagged
return;
}
FatalErrorInFunction FatalErrorInFunction
<< "Overflow : sum of sizes exceeds labelMax (" << "Overflow : sum of sizes exceeds labelMax ("
<< labelMax << ") after index " << idx; << labelMax << ") after index " << idx;
if (!localLens.empty()) if (prevOffset >= 0 && count >= 0)
{ {
FatalError << " of " << flatOutput(localLens); FatalError
<< " while trying to add (" << count
<< ") to offset (" << prevOffset << ")";
} }
FatalError FatalError
@ -70,27 +79,29 @@ Foam::globalIndex::calcRange
} }
const label myProci = UPstream::myProcNo(comm); const label myProci = UPstream::myProcNo(comm);
const labelList localLens = UPstream::allGatherValues(localSize, comm); const labelList counts = UPstream::allGatherValues(localSize, comm);
if (checkOverflow) if (checkOverflow)
{ {
const label len = localLens.size(); const label len = counts.size();
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = counts[i];
if (i == myProci) if (i == myProci)
{ {
myRange.start() = start; myRange.start() = start;
} }
const label prev = start; const label prev = start;
start += localLens[i]; start += count;
if (start < prev) if (start < prev)
{ {
reportOverflowAndExit(i, localLens); reportOverflowAndExit(i, prev, count);
} }
} }
} }
@ -98,8 +109,8 @@ Foam::globalIndex::calcRange
{ {
// std::accumulate // std::accumulate
// ( // (
// localLens.cbegin(), // counts.cbegin(),
// localLens.cbegin(myProci), // counts.cbegin(myProci),
// label(0) // label(0)
// ); // );
@ -107,7 +118,7 @@ Foam::globalIndex::calcRange
for (label i = 0; i < myProci; ++i) for (label i = 0; i < myProci; ++i)
{ {
start += localLens[i]; start += counts[i];
} }
myRange.start() = start; myRange.start() = start;
} }
@ -133,27 +144,28 @@ Foam::globalIndex::calcOffset
} }
const label myProci = UPstream::myProcNo(comm); const label myProci = UPstream::myProcNo(comm);
const labelList localLens = UPstream::allGatherValues(localSize, comm); const labelList counts = UPstream::allGatherValues(localSize, comm);
if (checkOverflow) if (checkOverflow)
{ {
const label len = localLens.size(); const label len = counts.size();
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = counts[i];
if (i == myProci) if (i == myProci)
{ {
myOffset = start; myOffset = start;
} }
const label prev = start; const label prev = start;
start += localLens[i]; start += count;
if (start < prev) if (start < prev)
{ {
reportOverflowAndExit(i, localLens); reportOverflowAndExit(i, prev, count);
} }
} }
} }
@ -161,8 +173,8 @@ Foam::globalIndex::calcOffset
{ {
// std::accumulate // std::accumulate
// ( // (
// localLens.cbegin(), // counts.cbegin(),
// localLens.cbegin(myProci), // counts.cbegin(myProci),
// label(0) // label(0)
// ); // );
@ -170,7 +182,7 @@ Foam::globalIndex::calcOffset
for (label i = 0; i < myProci; ++i) for (label i = 0; i < myProci; ++i)
{ {
start += localLens[i]; start += counts[i];
} }
myOffset = start; myOffset = start;
} }
@ -182,13 +194,13 @@ Foam::globalIndex::calcOffset
Foam::labelList Foam::labelList
Foam::globalIndex::calcOffsets Foam::globalIndex::calcOffsets
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow const bool checkOverflow
) )
{ {
labelList values; labelList values;
const label len = localLens.size(); const label len = counts.size();
if (len) if (len)
{ {
@ -197,12 +209,13 @@ Foam::globalIndex::calcOffsets
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = counts[i];
values[i] = start; values[i] = start;
start += localLens[i]; start += count;
if (checkOverflow && start < values[i]) if (checkOverflow && start < values[i])
{ {
reportOverflowAndExit(i, localLens); reportOverflowAndExit(i, values[i], count);
} }
} }
values[len] = start; values[len] = start;
@ -215,13 +228,13 @@ Foam::globalIndex::calcOffsets
Foam::List<Foam::labelRange> Foam::List<Foam::labelRange>
Foam::globalIndex::calcRanges Foam::globalIndex::calcRanges
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow const bool checkOverflow
) )
{ {
List<labelRange> values; List<labelRange> values;
const label len = localLens.size(); const label len = counts.size();
if (len) if (len)
{ {
@ -230,12 +243,18 @@ Foam::globalIndex::calcRanges
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
values[i].reset(start, localLens[i]); const label count = counts[i];
start += localLens[i]; values[i].reset(start, count);
start += count;
if (checkOverflow && start < values[i].start()) if
(
checkOverflow
&& (start < values[i].start())
&& (i < len-1) // Do not check the one beyond the end range
)
{ {
reportOverflowAndExit(i, localLens); reportOverflowAndExit(i, values[i].start(), count);
} }
} }
} }
@ -328,11 +347,11 @@ void Foam::globalIndex::reset
if (len) if (len)
{ {
labelList localLens; labelList counts;
if (parallel && UPstream::parRun()) // or UPstream::is_parallel(comm) if (parallel && UPstream::parRun()) // or UPstream::is_parallel(comm)
{ {
localLens = UPstream::allGatherValues(localSize, comm); counts = UPstream::allGatherValues(localSize, comm);
} }
else else
{ {
@ -340,11 +359,11 @@ void Foam::globalIndex::reset
// TBD: check for (proci >= 0) ? // TBD: check for (proci >= 0) ?
const auto proci = UPstream::myProcNo(comm); const auto proci = UPstream::myProcNo(comm);
localLens.resize(len, Zero); counts.resize(len, Zero);
localLens[proci] = localSize; counts[proci] = localSize;
} }
reset(localLens, true); // checkOverflow = true reset(counts, true); // checkOverflow = true
} }
else else
{ {
@ -356,11 +375,11 @@ void Foam::globalIndex::reset
void Foam::globalIndex::reset void Foam::globalIndex::reset
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow const bool checkOverflow
) )
{ {
const label len = localLens.size(); const label len = counts.size();
if (len) if (len)
{ {
@ -369,12 +388,13 @@ void Foam::globalIndex::reset
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = counts[i];
offsets_[i] = start; offsets_[i] = start;
start += localLens[i]; start += count;
if (checkOverflow && start < offsets_[i]) if (checkOverflow && start < offsets_[i])
{ {
reportOverflowAndExit(i, localLens); reportOverflowAndExit(i, offsets_[i], count);
} }
} }
offsets_[len] = start; offsets_[len] = start;
@ -468,8 +488,8 @@ Foam::label Foam::globalIndex::maxNonLocalSize(const label proci) const
{ {
if (i != proci) if (i != proci)
{ {
const label localLen = (offsets_[i+1] - offsets_[i]); const label count = (offsets_[i+1] - offsets_[i]);
maxLen = max(maxLen, localLen); maxLen = max(maxLen, count);
} }
} }
@ -506,17 +526,17 @@ Foam::labelRange Foam::globalIndex::back() const
} }
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, globalIndex& gi) Foam::Istream& Foam::operator>>(Istream& is, globalIndex& gi)
{ {
return is >> gi.offsets_; return is >> gi.offsets();
} }
Foam::Ostream& Foam::operator<<(Ostream& os, const globalIndex& gi) Foam::Ostream& Foam::operator<<(Ostream& os, const globalIndex& gi)
{ {
return os << gi.offsets_; return os << gi.offsets();
} }

View File

@ -83,11 +83,12 @@ class globalIndex
DynamicList<label>& validBins DynamicList<label>& validBins
); );
//- Report overflow at specified index //- Report overflow at specified (non-negative) index
static void reportOverflowAndExit static void reportOverflowAndExit
( (
const label idx, const label idx,
const labelUList& localLens = labelUList::null() const label prevOffset = -1, // The last valid offset value
const label count = 0 // The count to add to prevOffset
); );
public: public:
@ -122,7 +123,7 @@ public:
//- No communication required //- No communication required
inline explicit globalIndex(labelList&& listOffsets); inline explicit globalIndex(labelList&& listOffsets);
//- Copy construct from a list of sizes. //- Construct from a list of sizes and calculate the offsets.
//- No communication required //- No communication required
inline globalIndex inline globalIndex
( (
@ -265,12 +266,12 @@ public:
const bool parallel = UPstream::parRun() //!< use parallel comms const bool parallel = UPstream::parRun() //!< use parallel comms
); );
//- Reset from list of local sizes, //- Reset offsets from a list of local sizes,
//- with optional check for label overflow. //- with optional check for label overflow.
//- No communication required //- No communication required
void reset void reset
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow = false const bool checkOverflow = false
); );
@ -307,6 +308,9 @@ public:
const label comm = UPstream::worldComm //!< communicator const label comm = UPstream::worldComm //!< communicator
); );
//- Reset the globalIndex. Same as copy assignment.
inline void reset(const globalIndex& gi);
//- Alter local size for given processor //- Alter local size for given processor
void setLocalSize(const label proci, const label len); void setLocalSize(const label proci, const label len);
@ -504,7 +508,7 @@ public:
//- with optional check for label overflow //- with optional check for label overflow
static labelList calcOffsets static labelList calcOffsets
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow = false const bool checkOverflow = false
); );
@ -521,7 +525,7 @@ public:
//- with optional check for label overflow //- with optional check for label overflow
static List<labelRange> calcRanges static List<labelRange> calcRanges
( (
const labelUList& localLens, const labelUList& counts,
const bool checkOverflow = false const bool checkOverflow = false
); );
@ -955,6 +959,27 @@ public:
) const; ) const;
// Member Operators
//- Compare for equality - uses the offsets
bool operator==(const globalIndex& rhs) const
{
return (this->offsets() == rhs.offsets());
}
//- Compare for inequality - uses the offsets
bool operator!=(const globalIndex& rhs) const
{
return !(*this == rhs);
}
//- Compare for less-than - uses the offsets
bool operator<(const globalIndex& rhs) const
{
return (this->offsets() < rhs.offsets());
}
// IOstream Operators // IOstream Operators
friend Istream& operator>>(Istream& is, globalIndex& gi); friend Istream& operator>>(Istream& is, globalIndex& gi);

View File

@ -467,6 +467,16 @@ inline void Foam::globalIndex::reset
} }
inline void Foam::globalIndex::reset(const globalIndex& rhs)
{
if (this == &rhs)
{
return; // Self-assignment is a no-op
}
this->offsets_ = rhs.offsets_;
}
// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * //
inline Foam::globalIndex::const_iterator:: inline Foam::globalIndex::const_iterator::

View File

@ -49,12 +49,14 @@ Foam::globalIndex::calcListOffsets
label start = 0; label start = 0;
for (label i = 0; i < len; ++i) for (label i = 0; i < len; ++i)
{ {
const label count = lists[i].size();
values[i] = start; values[i] = start;
start += lists[i].size(); start += count;
if (checkOverflow && start < values[i]) if (checkOverflow && start < values[i])
{ {
reportOverflowAndExit(i); reportOverflowAndExit(i, values[i], count);
} }
} }
values[len] = start; values[len] = start;
@ -1005,12 +1007,12 @@ OutputContainer Foam::globalIndex::scatter
// The globalIndex might be correct on master only, // The globalIndex might be correct on master only,
// so scatter local sizes to ensure consistency // so scatter local sizes to ensure consistency
const label localLen const label count
( (
UPstream::listScatterValues<label>(this->localSizes(), comm) UPstream::listScatterValues<label>(this->localSizes(), comm)
); );
OutputContainer localData(localLen); OutputContainer localData(count);
this->scatter(allData, localData, tag, commsType, comm); this->scatter(allData, localData, tag, commsType, comm);
return localData; return localData;