mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: reduces buffer use / blocking in Ensight output
- reuse single component buffer within an Ensight output method. Use direct UPstream read/write to avoid Pstream char buffers - replace blocking transfer with scheduled for Ensight cloud output
This commit is contained in:
@ -50,6 +50,7 @@ SourceFiles
|
||||
#include "ListOps.H"
|
||||
#include "ListListOps.H"
|
||||
#include "IndirectList.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -260,17 +261,27 @@ labelList getPolysNFaces(const polyMesh& mesh, const labelUList& addr);
|
||||
labelList getPolysNPointsPerFace(const polyMesh& mesh, const labelUList& addr);
|
||||
|
||||
|
||||
//- Copy specified field component into a scalarField
|
||||
// works for various lists types
|
||||
//- Copy specified field component into a scalar buffer
|
||||
//- works for various lists types. Must be adequately sized before calling
|
||||
template<template<typename> class FieldContainer, class Type>
|
||||
void copyComponent
|
||||
(
|
||||
scalarField& res,
|
||||
List<scalar>& cmptBuffer,
|
||||
const FieldContainer<Type>& input,
|
||||
const direction cmpt
|
||||
);
|
||||
|
||||
|
||||
//- Write field content (component-wise)
|
||||
template<template<typename> class FieldContainer, class Type>
|
||||
void writeFieldContent
|
||||
(
|
||||
ensightFile& os,
|
||||
const FieldContainer<Type>& fld,
|
||||
bool parallel //!< Collective write?
|
||||
);
|
||||
|
||||
|
||||
//- Write coordinates (component-wise) for the given part
|
||||
template<template<typename> class FieldContainer>
|
||||
bool writeCoordinates
|
||||
|
||||
@ -27,20 +27,27 @@ License
|
||||
|
||||
#include "ensightOutput.H"
|
||||
#include "ensightPTraits.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<template<typename> class FieldContainer, class Type>
|
||||
void Foam::ensightOutput::Detail::copyComponent
|
||||
(
|
||||
scalarField& res,
|
||||
List<scalar>& cmptBuffer,
|
||||
const FieldContainer<Type>& input,
|
||||
const direction cmpt
|
||||
)
|
||||
{
|
||||
res.resize(input.size());
|
||||
if (cmptBuffer.size() < input.size())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Component buffer too small: "
|
||||
<< cmptBuffer.size() << " < " << input.size() << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
auto iter = res.begin();
|
||||
auto iter = cmptBuffer.begin();
|
||||
|
||||
for (const Type& val : input)
|
||||
{
|
||||
@ -50,6 +57,80 @@ void Foam::ensightOutput::Detail::copyComponent
|
||||
}
|
||||
|
||||
|
||||
template<template<typename> class FieldContainer, class Type>
|
||||
void Foam::ensightOutput::Detail::writeFieldContent
|
||||
(
|
||||
ensightFile& os,
|
||||
const FieldContainer<Type>& fld,
|
||||
bool parallel
|
||||
)
|
||||
{
|
||||
// already checked prior to calling, but extra safety
|
||||
parallel = parallel && Pstream::parRun();
|
||||
|
||||
// Size information (offsets are irrelevant)
|
||||
globalIndex procAddr;
|
||||
if (parallel)
|
||||
{
|
||||
procAddr.reset(UPstream::listGatherValues<label>(fld.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Master size
|
||||
procAddr.reset(labelList(Foam::one{}, fld.size()));
|
||||
}
|
||||
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
DynamicList<scalar> cmptBuffer(procAddr.maxSize());
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt = ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
// Write master data
|
||||
cmptBuffer.resize_nocopy(procAddr.localSize(0));
|
||||
copyComponent(cmptBuffer, fld, cmpt);
|
||||
os.writeList(cmptBuffer);
|
||||
|
||||
// Receive and write
|
||||
for (const label proci : procAddr.subProcs())
|
||||
{
|
||||
cmptBuffer.resize_nocopy(procAddr.localSize(proci));
|
||||
UIPstream::read
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
proci,
|
||||
cmptBuffer.data_bytes(),
|
||||
cmptBuffer.size_bytes()
|
||||
);
|
||||
os.writeList(cmptBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parallel)
|
||||
{
|
||||
// Send
|
||||
List<scalar> cmptBuffer(fld.size());
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt = ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
copyComponent(cmptBuffer, fld, cmpt);
|
||||
UOPstream::write
|
||||
(
|
||||
UPstream::commsTypes::scheduled,
|
||||
Pstream::masterNo(),
|
||||
cmptBuffer.cdata_bytes(),
|
||||
cmptBuffer.size_bytes()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<template<typename> class FieldContainer>
|
||||
bool Foam::ensightOutput::Detail::writeCoordinates
|
||||
(
|
||||
@ -63,57 +144,13 @@ bool Foam::ensightOutput::Detail::writeCoordinates
|
||||
{
|
||||
parallel = parallel && Pstream::parRun();
|
||||
|
||||
const IntRange<int> senders =
|
||||
(
|
||||
parallel
|
||||
? Pstream::subProcs()
|
||||
: IntRange<int>()
|
||||
);
|
||||
|
||||
|
||||
// Using manual copyComponent(...) instead of fld.component() to support
|
||||
// indirect lists etc.
|
||||
|
||||
scalarField send(fld.size());
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
os.beginPart(partId, partName);
|
||||
os.beginCoordinates(nPoints);
|
||||
|
||||
for (direction cmpt=0; cmpt < point::nComponents; ++cmpt)
|
||||
{
|
||||
// Main
|
||||
copyComponent(send, fld, cmpt);
|
||||
os.writeList(send);
|
||||
|
||||
// Others
|
||||
for (const int proci : senders)
|
||||
{
|
||||
IPstream fromOther(Pstream::commsTypes::scheduled, proci);
|
||||
scalarField recv(fromOther);
|
||||
|
||||
os.writeList(recv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (senders)
|
||||
{
|
||||
// Send from other (parallel)
|
||||
|
||||
for (direction cmpt=0; cmpt < point::nComponents; ++cmpt)
|
||||
{
|
||||
copyComponent(send, fld, cmpt);
|
||||
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::commsTypes::scheduled,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
|
||||
toMaster << send;
|
||||
}
|
||||
}
|
||||
ensightOutput::Detail::writeFieldContent(os, fld, parallel);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -130,14 +167,6 @@ bool Foam::ensightOutput::Detail::writeFieldComponents
|
||||
{
|
||||
parallel = parallel && Pstream::parRun();
|
||||
|
||||
const IntRange<int> senders =
|
||||
(
|
||||
parallel
|
||||
? Pstream::subProcs()
|
||||
: IntRange<int>()
|
||||
);
|
||||
|
||||
|
||||
// Preliminary checks
|
||||
{
|
||||
bool hasField = !fld.empty();
|
||||
@ -152,52 +181,12 @@ bool Foam::ensightOutput::Detail::writeFieldComponents
|
||||
}
|
||||
|
||||
|
||||
// Using manual copyComponent(...) instead of fld.component() to support
|
||||
// indirect lists etc.
|
||||
|
||||
scalarField send(fld.size());
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
os.writeKeyword(key);
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt = ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
// Main
|
||||
copyComponent(send, fld, cmpt);
|
||||
os.writeList(send);
|
||||
|
||||
// Others
|
||||
for (const int proci : senders)
|
||||
{
|
||||
IPstream fromOther(Pstream::commsTypes::scheduled, proci);
|
||||
scalarField recv(fromOther);
|
||||
|
||||
os.writeList(recv);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (senders)
|
||||
{
|
||||
// Send from other (parallel)
|
||||
|
||||
for (direction d=0; d < pTraits<Type>::nComponents; ++d)
|
||||
{
|
||||
const direction cmpt = ensightPTraits<Type>::componentOrder[d];
|
||||
|
||||
copyComponent(send, fld, cmpt);
|
||||
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::commsTypes::scheduled,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
|
||||
toMaster << send;
|
||||
}
|
||||
}
|
||||
ensightOutput::Detail::writeFieldContent(os, fld, parallel);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -294,6 +283,7 @@ bool Foam::ensightOutput::Detail::writeFaceLocalField
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
os.beginPart(part.index());
|
||||
@ -345,6 +335,7 @@ bool Foam::ensightOutput::writeField
|
||||
if (!hasField) return false;
|
||||
}
|
||||
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
os.beginPart(part.index());
|
||||
|
||||
Reference in New Issue
Block a user