Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework BP5 Attribute handling #3304

Merged
merged 17 commits into from
Aug 15, 2022
7 changes: 7 additions & 0 deletions source/adios2/core/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ void Engine::InitTransports() {}

void Engine::NotifyEngineAttribute(std::string name, DataType type) noexcept {}

// if not overriden, default to name/type version
void Engine::NotifyEngineAttribute(std::string name, AttributeBase *attr,
void *Data) noexcept
{
NotifyEngineAttribute(name, attr->m_Type);
}

void Engine::NotifyEngineNoVarsQuery() {}

// DoPut*
Expand Down
2 changes: 2 additions & 0 deletions source/adios2/core/Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@ class Engine
*/
virtual void NotifyEngineAttribute(std::string name,
DataType type) noexcept;
virtual void NotifyEngineAttribute(std::string name, AttributeBase *attr,
void *Data) noexcept;

/** Notify the engine when InquireVariable is called when the IO is empty.
* Called from IO.tcc
Expand Down
84 changes: 50 additions & 34 deletions source/adios2/core/IO.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -126,31 +126,34 @@ Attribute<T> &IO::DefineAttribute(const std::string &name, const T &value,
auto itExistingAttribute = m_Attributes.find(globalName);
if (itExistingAttribute != m_Attributes.end())
{
if (itExistingAttribute->second->m_Type == helper::GetDataType<T>())
if (helper::ValueToString(value) !=
itExistingAttribute->second->GetInfo()["Value"])
{
if (!itExistingAttribute->second->Equals(
static_cast<const void *>(&value), 1))
if (itExistingAttribute->second->m_Type == helper::GetDataType<T>())
{

Attribute<T> &a =
static_cast<Attribute<T> &>(*itExistingAttribute->second);

a.Modify(value);
void *Data = &a.m_DataSingleValue;
if (a.m_DataArray.size() != 0)
Data = a.m_DataArray.data();
for (auto &e : m_Engines)
{
e.second->NotifyEngineAttribute(
globalName, itExistingAttribute->second->m_Type);
globalName, itExistingAttribute->second.get(), Data);
}
}
}
else
{
helper::Throw<std::invalid_argument>(
"Core", "IO", "DefineAttribute",
"modifiable attribute " + globalName +
" has been defined with type " +
ToString(itExistingAttribute->second->m_Type) +
". Type cannot be changed to " +
ToString(helper::GetDataType<T>()));
else
{
helper::Throw<std::invalid_argument>(
"Core", "IO", "DefineAttribute",
"modifiable attribute " + globalName +
" has been defined with type " +
ToString(itExistingAttribute->second->m_Type) +
". Type cannot be changed to " +
ToString(helper::GetDataType<T>()));
}
}
return static_cast<Attribute<T> &>(*itExistingAttribute->second);
}
Expand All @@ -161,8 +164,14 @@ Attribute<T> &IO::DefineAttribute(const std::string &name, const T &value,
globalName, value, allowModification)));
for (auto &e : m_Engines)
{
Attribute<T> &a =
static_cast<Attribute<T> &>(*itAttributePair.first->second);
void *Data = &a.m_DataSingleValue;
if (a.m_DataArray.size() != 0)
Data = a.m_DataArray.data();

e.second->NotifyEngineAttribute(
globalName, itAttributePair.first->second->m_Type);
globalName, itAttributePair.first->second.get(), Data);
}
return static_cast<Attribute<T> &>(*itAttributePair.first->second);
}
Expand Down Expand Up @@ -191,31 +200,36 @@ IO::DefineAttribute(const std::string &name, const T *array,
auto itExistingAttribute = m_Attributes.find(globalName);
if (itExistingAttribute != m_Attributes.end())
{
if (itExistingAttribute->second->m_Type == helper::GetDataType<T>())
const std::string arrayValues(
"{ " +
helper::VectorToCSV(std::vector<T>(array, array + elements)) +
" }");

if (itExistingAttribute->second->GetInfo()["Value"] != arrayValues)
{
if (!itExistingAttribute->second->Equals(
static_cast<const void *>(array), elements))
if (itExistingAttribute->second->m_Type == helper::GetDataType<T>())
{

Attribute<T> &a =
static_cast<Attribute<T> &>(*itExistingAttribute->second);
a.Modify(array, elements);
void *Data = &a.m_DataSingleValue;
if (a.m_DataArray.size() != 0)
Data = a.m_DataArray.data();
for (auto &e : m_Engines)
{
e.second->NotifyEngineAttribute(
globalName, itExistingAttribute->second->m_Type);
e.second->NotifyEngineAttribute(globalName, &a, Data);
}
}
}
else
{
helper::Throw<std::invalid_argument>(
"Core", "IO", "DefineAttribute",
"modifiable attribute " + globalName +
" has been defined with type " +
ToString(itExistingAttribute->second->m_Type) +
". Type cannot be changed to " +
ToString(helper::GetDataType<T>()));
else
{
helper::Throw<std::invalid_argument>(
"Core", "IO", "DefineAttribute",
"modifiable attribute " + globalName +
" has been defined with type " +
ToString(itExistingAttribute->second->m_Type) +
". Type cannot be changed to " +
ToString(helper::GetDataType<T>()));
}
}
return static_cast<Attribute<T> &>(*itExistingAttribute->second);
}
Expand All @@ -224,10 +238,12 @@ IO::DefineAttribute(const std::string &name, const T *array,
auto itAttributePair = m_Attributes.emplace(
globalName, std::unique_ptr<AttributeBase>(new Attribute<T>(
globalName, array, elements, allowModification)));
Attribute<T> &a =
static_cast<Attribute<T> &>(*itAttributePair.first->second);
void *Data = (void *)array;
for (auto &e : m_Engines)
{
e.second->NotifyEngineAttribute(
globalName, itAttributePair.first->second->m_Type);
e.second->NotifyEngineAttribute(globalName, &a, Data);
}
return static_cast<Attribute<T> &>(*itAttributePair.first->second);
}
Expand Down
6 changes: 6 additions & 0 deletions source/adios2/engine/bp4/BP4Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,12 @@ void BP4Writer::NotifyEngineAttribute(std::string name, DataType type) noexcept
m_BP4Serializer.m_SerializedAttributes.erase(name);
}

void BP4Writer::NotifyEngineAttribute(std::string name, AttributeBase *attr,
void *Data) noexcept
{
NotifyEngineAttribute(name, attr->m_Type);
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
2 changes: 2 additions & 0 deletions source/adios2/engine/bp4/BP4Writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ class BP4Writer : public core::Engine
void PerformPutCommon(Variable<T> &variable);

void NotifyEngineAttribute(std::string name, DataType type) noexcept;
virtual void NotifyEngineAttribute(std::string name, AttributeBase *attr,
void *Data) noexcept;
};

} // end namespace engine
Expand Down
1 change: 1 addition & 0 deletions source/adios2/engine/bp5/BP5Engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class BP5Engine
MACRO(StatsLevel, UInt, unsigned int, 1) \
MACRO(StatsBlockSize, SizeBytes, size_t, DefaultStatsBlockSize) \
MACRO(Threads, UInt, unsigned int, 0) \
MACRO(UseOneTimeAttributes, Bool, bool, true) \
MACRO(MaxOpenFilesAtOnce, UInt, unsigned int, UINT_MAX)

struct BP5Params
Expand Down
27 changes: 26 additions & 1 deletion source/adios2/engine/bp5/BP5Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ StepStatus BP5Writer::BeginStep(StepMode mode, const float timeoutSeconds)
}
}

if ((m_WriterStep == 0) && m_Parameters.UseOneTimeAttributes)
{
const auto &attributes = m_IO.GetAttributes();

for (const auto &attributePair : attributes)
{
m_BP5Serializer.OnetimeMarshalAttribute(*(attributePair.second));
}
}

if (m_Parameters.AsyncWrite)
{
m_AsyncWriteLock.lock();
Expand Down Expand Up @@ -422,7 +432,22 @@ void BP5Writer::WriteMetadataFileIndex(uint64_t MetaDataPos,

void BP5Writer::NotifyEngineAttribute(std::string name, DataType type) noexcept
{
m_MarshalAttributesNecessary = true;
helper::Throw<std::invalid_argument>(
"BP5Writer", "Engine", "ThrowUp",
"Engine does not support NotifyEngineAttribute");
}

void BP5Writer::NotifyEngineAttribute(std::string name, AttributeBase *Attr,
void *data) noexcept
{
if (!m_Parameters.UseOneTimeAttributes)
{
m_MarshalAttributesNecessary = true;
return;
}

m_BP5Serializer.OnetimeMarshalAttribute(*Attr);
m_MarshalAttributesNecessary = false;
}

void BP5Writer::MarshalAttributes()
Expand Down
2 changes: 2 additions & 0 deletions source/adios2/engine/bp5/BP5Writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class BP5Writer : public BP5Engine, public core::Engine
/** Notify the engine when a new attribute is defined or modified. Called
* from IO.tcc
*/
void NotifyEngineAttribute(std::string name, AttributeBase *Attr,
void *data) noexcept;

void EnterComputationBlock() noexcept;
/** Inform about computation block through User->ADIOS->IO */
Expand Down
34 changes: 30 additions & 4 deletions source/adios2/engine/sst/SstWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Distributed under the OSI-approved Apache License, Version 2.0. See
* accompanying file Copyright.txt for details.
*
* Sst.cpp
* SstWriter.cpp
*
* Created on: Aug 17, 2017
* Author: Greg Eisenhauer
Expand Down Expand Up @@ -187,10 +187,16 @@ void SstWriter::MarshalAttributes()
PERFSTUBS_SCOPED_TIMER_FUNC();
const auto &attributes = m_IO.GetAttributes();

const uint32_t attributesCount = static_cast<uint32_t>(attributes.size());
if ((m_WriterStep == 0) && Params.UseOneTimeAttributes)
{
for (const auto &attributePair : attributes)
{
m_BP5Serializer->OnetimeMarshalAttribute(*(attributePair.second));
}
}

// if there are no new attributes, nothing to do
if (attributesCount == m_MarshaledAttributesCount)
if (!m_MarshalAttributesNecessary)
return;

for (const auto &attributePair : attributes)
Expand Down Expand Up @@ -245,7 +251,27 @@ void SstWriter::MarshalAttributes()
ADIOS2_FOREACH_ATTRIBUTE_PRIMITIVE_STDTYPE_1ARG(declare_type)
#undef declare_type
}
m_MarshaledAttributesCount = attributesCount;
m_MarshalAttributesNecessary = false;
}

void SstWriter::NotifyEngineAttribute(std::string name, DataType type) noexcept
{
helper::Throw<std::invalid_argument>(
"SstWriter", "Engine", "ThrowUp",
"Engine does not support NotifyEngineAttribute");
}

void SstWriter::NotifyEngineAttribute(std::string name, AttributeBase *Attr,
void *data) noexcept
{
if (!Params.UseOneTimeAttributes)
{
m_MarshalAttributesNecessary = true;
return;
}

m_BP5Serializer->OnetimeMarshalAttribute(*Attr);
m_MarshalAttributesNecessary = false;
}

void SstWriter::EndStep()
Expand Down
5 changes: 4 additions & 1 deletion source/adios2/engine/sst/SstWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class SstWriter : public Engine
void PerformPuts() final;
void EndStep() final;
void Flush(const int transportIndex = -1) final;
void NotifyEngineAttribute(std::string name, DataType type) noexcept;
void NotifyEngineAttribute(std::string name, AttributeBase *Attr,
void *data) noexcept;

/**
* Called if destructor is called on an open engine. Should warn or take
Expand Down Expand Up @@ -85,7 +88,7 @@ class SstWriter : public Engine
SstStream m_Output;
long m_WriterStep = -1;
bool m_DefinitionsNotified = false;
size_t m_MarshaledAttributesCount = 0;
bool m_MarshalAttributesNecessary = true; // first time through, marshal
struct _SstParams Params;

void MarshalAttributes();
Expand Down
76 changes: 76 additions & 0 deletions source/adios2/toolkit/format/bp5/BP5Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,82 @@ class BP5Base
size_t DataBlockSize;
};

struct PrimitiveTypeAttr
{
const char *Name = NULL;
size_t TotalElementSize = 0;
char *Values;
};

struct StringArrayAttr
{
const char *Name = NULL;
size_t ElementCount = 0;
const char **Values = NULL;
};

struct BP5AttrStruct
{
size_t PrimAttrCount = 0;
struct PrimitiveTypeAttr *PrimAttrs =
(struct PrimitiveTypeAttr *)malloc(1);
size_t StrAttrCount = 0;
struct StringArrayAttr *StrAttrs = (struct StringArrayAttr *)malloc(1);
};

size_t DataTypeSize[(int)DataType::Struct + 1] = {
0, // None
1, // Int8
2, // Int16
4, // Int32
8, // Int64
1, // UInt8
2, // UInt16
4, // UInt32
8, // UInt64
sizeof(float), // Float
sizeof(double), // Double
sizeof(long double), // LongDouble
sizeof(cfloat), // FloatComplex
sizeof(cdouble), // DoubleComplex
0, // String
1, // Char
0, // Struct
};

FMField prim_attr_field_list[4] = {
{"name", "string", sizeof(char *), FMOffset(PrimitiveTypeAttr *, Name)},
{"TotalElementSize", "integer", sizeof(size_t),
FMOffset(PrimitiveTypeAttr *, TotalElementSize)},
{"Values", "char[TotalElementSize]", 1,
FMOffset(PrimitiveTypeAttr *, Values)},
{NULL, NULL, 0, 0}};

FMField string_attr_field_list[4] = {
{"name", "string", sizeof(char *), FMOffset(StringArrayAttr *, Name)},
{"ElementCount", "integer", sizeof(size_t),
FMOffset(StringArrayAttr *, ElementCount)},
{"Values", "string[ElementCount]", sizeof(char *),
FMOffset(StringArrayAttr *, Values)},
{NULL, NULL, 0, 0}};

FMField bp5_attr_field_list[5] = {
{"PrimAttrCount", "integer", sizeof(size_t),
FMOffset(BP5AttrStruct *, PrimAttrCount)},
{"PrimAttrs", "PrimAttr[PrimAttrCount]", sizeof(PrimitiveTypeAttr),
FMOffset(BP5AttrStruct *, PrimAttrs)},
{"StrAttrCount", "integer", sizeof(size_t),
FMOffset(BP5AttrStruct *, StrAttrCount)},
{"StrAttrs", "StrAttr[StrAttrCount]", sizeof(StringArrayAttr),
FMOffset(BP5AttrStruct *, StrAttrs)},
{NULL, NULL, 0, 0}};

FMStructDescRec attr_struct_list[4] = {
{"GenericAttributes", bp5_attr_field_list, sizeof(BP5AttrStruct), NULL},
{"PrimAttr", prim_attr_field_list, sizeof(PrimitiveTypeAttr), NULL},
{"StrAttr", string_attr_field_list, sizeof(StringArrayAttr), NULL},
{NULL, NULL, 0, NULL}};

void BP5BitfieldSet(struct BP5MetadataInfoStruct *MBase, int Bit) const;
int BP5BitfieldTest(struct BP5MetadataInfoStruct *MBase, int Bit) const;
FMField *MetaArrayRecListPtr;
Expand Down
Loading