From c83faffafd4d8147a090e861ee74286debfbf7d6 Mon Sep 17 00:00:00 2001 From: Norbert Podhorszki <pnorbert@ornl.gov> Date: Thu, 6 Apr 2017 17:05:44 -0400 Subject: [PATCH] Added Selections and Variable.SetSelection(), and use them in heatTransfer example. --- examples/heatTransfer/IO_adios2.cpp | 48 ++++++------- include/core/VariableBase.h | 57 ++++++++++++++- .../adios_selection.h} | 19 +++-- include/functions/adiosFunctions.h | 9 ++- include/selection/Selection.h | 70 +++++++++++++++++++ include/selection/SelectionBoundingBox.h | 38 ++++++++++ include/selection/SelectionPoints.h | 55 +++++++++++++++ source/functions/adiosFunctions.cpp | 11 +++ 8 files changed, 274 insertions(+), 33 deletions(-) rename include/{ADIOS_SELECTION.h => external/adios_selection.h} (97%) create mode 100644 include/selection/Selection.h create mode 100644 include/selection/SelectionBoundingBox.h create mode 100644 include/selection/SelectionPoints.h diff --git a/examples/heatTransfer/IO_adios2.cpp b/examples/heatTransfer/IO_adios2.cpp index ac0567820..966bfae20 100644 --- a/examples/heatTransfer/IO_adios2.cpp +++ b/examples/heatTransfer/IO_adios2.cpp @@ -31,7 +31,7 @@ IO::IO(const Settings &s, MPI_Comm comm) if (!bpWriterSettings.isUserDefined()) { // if not defined by user, we can change the default settings - bpWriterSettings.SetEngine("BP"); // BP is the default engine + bpWriterSettings.SetEngine("BPFileWriter"); // BP is the default engine bpWriterSettings.AllowThreads( 1); // allow 1 extra thread for data processing bpWriterSettings.AddTransport( @@ -47,11 +47,13 @@ IO::IO(const Settings &s, MPI_Comm comm) // define T as 2D global array varT = &ad->DefineVariable<double>( - "T", {s.gndx, s.gndy}, // Global dimensions - {s.ndx, - s.ndy}, // local size, could be defined later using SetSelection() - {s.offsx, s.offsy} // offset of the local array in the global space - ); + "T", + // Global dimensions + {s.gndx, s.gndy}, + // local size, could be defined later using SetSelection() + {s.ndx, s.ndy}, + // offset of the local array in the global space + {s.offsx, s.offsy}); // add transform to variable // adios::Transform tr = adios::transform::BZIP2( ); @@ -71,28 +73,19 @@ IO::~IO() delete ad; } -void /*IO::*/ old_style_write(int step, const HeatTransfer &ht, - const Settings &s, MPI_Comm comm) -{ - bpWriter->Write<double>(*varT, ht.data_noghost().data()); - bpWriter->Advance(); -} - void IO::write(int step, const HeatTransfer &ht, const Settings &s, MPI_Comm comm) { +#if 1 + /* This selection is redundant and not required, since we defined * the selection already in DefineVariable(). It is here just as an example. */ // Make a selection to describe the local dimensions of the variable we - // write - // and - // its offsets in the global spaces. This could have been done in + // write and its offsets in the global spaces. This could have been done in // adios.DefineVariable() - adios::Selection sel = adios.SelectionBoundingBox( - {s.ndx, s.ndy}, - {s.offsx, s.offsy}); // local dims and offsets; both as list - var2D.SetSelection(sel); + adios::SelectionBoundingBox sel({s.ndx, s.ndy}, {s.offsx, s.offsy}); + varT->SetSelection(sel); /* Select the area that we want to write from the data pointer we pass to the @@ -105,10 +98,17 @@ void IO::write(int step, const HeatTransfer &ht, const Settings &s, above. Default memspace is always the full selection. */ - adios::Selection memspace = - adios.SelectionBoundingBox({s.ndx, s.ndy}, {1, 1}); - var2D.SetMemorySelection(memspace); + adios::SelectionBoundingBox memspace = + adios::SelectionBoundingBox({s.ndx, s.ndy}, {1, 1}); + varT->SetMemorySelection(memspace); - bpWriter->Write<double>(*varT, ht.data()); + bpWriter->Write<double>(*varT, ht.data_noghost().data()); bpWriter->Advance(); + +#else + + bpWriter->Write<double>(*varT, ht.data_noghost().data()); + bpWriter->Advance(); + +#endif } diff --git a/include/core/VariableBase.h b/include/core/VariableBase.h index eea1d261c..d9d98c916 100644 --- a/include/core/VariableBase.h +++ b/include/core/VariableBase.h @@ -12,14 +12,16 @@ #define VARIABLEBASE_H_ /// \cond EXCLUDE_FROM_DOXYGEN +#include <exception> #include <iterator> #include <sstream> #include <string> #include <vector> /// \endcond -#include "functions/adiosFunctions.h" //GetTotalSize -#include "functions/adiosTemplates.h" //GetType<T> +#include "functions/adiosFunctions.h" //GetTotalSize, ConvertUint64VectorToSizetVector +#include "functions/adiosTemplates.h" //GetType<T> +#include "selection/SelectionBoundingBox.h" //Selection namespace adios { @@ -71,11 +73,62 @@ public: return GetTotalSize(m_Dimensions); } + /** + * Set the local dimension and global offset of the variable using a + * selection + * Only bounding boxes are allowed + */ + void SetSelection(const SelectionBoundingBox &sel) + { + + if (m_GlobalDimensions.size() == 0) + { + throw std::invalid_argument("Variable.SetSelection() is an invalid " + "call for single value variables\n"); + } + if (m_GlobalDimensions.size() != sel.m_Count.size()) + { + throw std::invalid_argument("Variable.SetSelection() bounding box " + "dimension must equal the global " + "dimension of the variable\n"); + } + + ConvertUint64VectorToSizetVector(sel.m_Count, m_Dimensions); + ConvertUint64VectorToSizetVector(sel.m_Start, m_GlobalDimensions); + } + + /** + * Set the local dimension and global offset of the variable using a + * selection + * Only bounding boxes are allowed + */ + void SetMemorySelection(const SelectionBoundingBox &sel) + { + if (m_GlobalDimensions.size() == 0) + { + throw std::invalid_argument( + "Variable.SetMemorySelection() is an invalid " + "call for single value variables\n"); + } + if (m_GlobalDimensions.size() != sel.m_Count.size()) + { + throw std::invalid_argument( + "Variable.SetMemorySelection() bounding box " + "dimension must equal the global " + "dimension of the variable\n"); + } + + ConvertUint64VectorToSizetVector(sel.m_Count, m_MemoryDimensions); + ConvertUint64VectorToSizetVector(sel.m_Start, m_MemoryOffsets); + } + // protected: off for now Dims m_Dimensions; ///< array of local dimensions Dims m_GlobalDimensions; ///< array of global dimensions Dims m_GlobalOffsets; ///< array of global offsets + Dims m_MemoryDimensions; ///< array of memory dimensions + Dims m_MemoryOffsets; ///< array of memory offsets const bool m_DebugMode = false; std::string GetDimensionAsString() { return dimsToString(m_Dimensions); } diff --git a/include/ADIOS_SELECTION.h b/include/external/adios_selection.h similarity index 97% rename from include/ADIOS_SELECTION.h rename to include/external/adios_selection.h index 806ee9083..2e15d124e 100644 --- a/include/ADIOS_SELECTION.h +++ b/include/external/adios_selection.h @@ -1,10 +1,11 @@ /* * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. + * */ /* - * Selection API in C for ADIOS BP format + * Streaming/Chunking/Selection Read API in C for ADIOS BP format * * A SELECTION is the data ranges resulting from a QUERY over a file and * variable(s). @@ -30,12 +31,14 @@ * the application does not need to retrieve the selection to work on the read * data. */ -#ifndef __ADIOS_SELECTION_H__ -#define __ADIOS_SELECTION_H__ +#ifndef __ADIOS_SELECTION_C_H__ +#define __ADIOS_SELECTION_C_H__ -/// \cond EXCLUDE_FROM_DOXYGEN #include <stdint.h> -/// \endcond + +#ifdef __cplusplus +extern "C" { +#endif /*************************/ /* Types used in the API */ @@ -230,4 +233,8 @@ ADIOS_SELECTION *adios_selection_points_1DtoND(ADIOS_SELECTION *pointsinbox1D, #endif /*__INCLUDED_FROM_FORTRAN_API__*/ -#endif /*__ADIOS_SELECTION_H__*/ +#ifdef __cplusplus +} +#endif + +#endif /*__ADIOS_SELECTION_C_H__*/ diff --git a/include/functions/adiosFunctions.h b/include/functions/adiosFunctions.h index ab6edba1d..4f33c2267 100644 --- a/include/functions/adiosFunctions.h +++ b/include/functions/adiosFunctions.h @@ -182,6 +182,12 @@ BuildParametersMap(const std::vector<std::string> ¶meters, */ std::vector<int> CSVToVectorInt(const std::string csv); +/** Convert a vector of uint64_t elements to a vector of std::size_t elements + * @param input vector of uint64_t elements + * @param output vector of std::size_t elements + */ +void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in, + std::vector<std::size_t> &out); /** * Common strategy to check for heap buffer allocation for data and metadata * typically calculated in Write @@ -190,7 +196,8 @@ std::vector<int> CSVToVectorInt(const std::string csv); * buffers ( default = 1.5 ) * @param maxBufferSize user provided maximum buffer size * @param buffer to be reallocated - * @return true: must do a transport flush, false: buffer sizes are enough to + * @return true: must do a transport flush, false: buffer sizes are enough + * to * contain incoming data, no need for transport flush */ bool CheckBufferAllocation(const std::size_t newSize, const float growthFactor, diff --git a/include/selection/Selection.h b/include/selection/Selection.h new file mode 100644 index 000000000..70d4c8314 --- /dev/null +++ b/include/selection/Selection.h @@ -0,0 +1,70 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +/* + * Selection API in C++ + * + * A SELECTION is the data ranges resulting from a QUERY over a file and + * variable(s). + * + * A SELECTION can be a list of bounding boxes and point-sets. Other data + * structures + * are not supported. Any query will result in such a selection. + * Other selections are the write-block and auto. + * + * Write block is a block of data written + * by a writer process, it is identified by an index. If each writer outputs + * one block + * then the index equals to the rank of the write process. With multi-var + * writing and + * multiple steps in a file, index runs from 0 as rank 0 process' first block. + * + * Auto selection lets the read method to automatically choose what to return. + * It will + * be a block / blocks of selected writers. + * + * If a query is a simple bounding box, the selection is the bounding box + * itself, so + * the application does not need to retrieve the selection to work on the read + * data. + */ +#ifndef __ADIOS_SELECTION_H__ +#define __ADIOS_SELECTION_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include "external/adios_selection.h" +#include <stdint.h> +/// \endcond + +namespace adios +{ + +/*************************/ +/* Types used in the API */ +/*************************/ +/* Type of selection */ +enum class SelectionType +{ + // Contiguous block of data defined by offsets and counts in each + // dimension + BoundingBox = ADIOS_SELECTION_BOUNDINGBOX, + // List of individual points + Points = ADIOS_SELECTION_POINTS, + // Selection of an individual block written by a writer process + WriteBlock = ADIOS_SELECTION_WRITEBLOCK, + // Let the method decide what to return + Auto = ADIOS_SELECTION_AUTO +}; + +class Selection +{ +public: + Selection(const SelectionType t) : m_Type(t){}; + const SelectionType m_Type; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_H__*/ diff --git a/include/selection/SelectionBoundingBox.h b/include/selection/SelectionBoundingBox.h new file mode 100644 index 000000000..b110fd96e --- /dev/null +++ b/include/selection/SelectionBoundingBox.h @@ -0,0 +1,38 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef __ADIOS_SELECTION_BOUNDINGBOX_H__ +#define __ADIOS_SELECTION_BOUNDINGBOX_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <cstdint> +/// \endcond + +#include "selection/Selection.h" + +namespace adios +{ + +/** Boundingbox selection to read a subset of a non-scalar variable. + * @param start array of offsets to start reading in each dimension + * @param count number of data elements to read in each dimension + */ +class SelectionBoundingBox : public Selection +{ +public: + SelectionBoundingBox(const std::vector<std::uint64_t> start, + const std::vector<std::uint64_t> count) + : Selection(SelectionType::BoundingBox), m_Start(start), m_Count(count) + { + } + ~SelectionBoundingBox(){}; + + std::vector<std::uint64_t> m_Start; + std::vector<std::uint64_t> m_Count; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_BOUNDINGBOX_H__*/ diff --git a/include/selection/SelectionPoints.h b/include/selection/SelectionPoints.h new file mode 100644 index 000000000..13fa951cb --- /dev/null +++ b/include/selection/SelectionPoints.h @@ -0,0 +1,55 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + */ + +#ifndef __ADIOS_SELECTION_POINTS_H__ +#define __ADIOS_SELECTION_POINTS_H__ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <cstdint> +/// \endcond + +#include "selection/Selection.h" +#include "selection/SelectionBoundingBox.h" + +namespace adios +{ + +/** Selection for a selection of an enumeration of positions. + * @param ndim Number of dimensions + * @param npoints Number of points of the selection + * @param points 1D array of indices, compacted for all dimension + * (e.g. [i1,j1,k1,i2,j2,k2,...,in,jn,kn] for + * n points in a 3D space. + */ +class SelectionPoints : public Selection +{ +public: + SelectionPoints(std::size_t ndim, std::size_t npoints, + std::vector<std::uint64_t> &points) + : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints), + m_Points(points) + { + } + + ///< C-style constructor to be used in the C-to-C++ wrapper + SelectionPoints(std::size_t ndim, std::size_t npoints, uint64_t *points) + : Selection(SelectionType::Points), m_Ndim(ndim), m_Npoints(npoints), + m_Points(std::vector<std::uint64_t>()), m_PointsC(points) + { + } + + ~SelectionPoints(){}; + + const std::size_t m_Ndim; + const std::size_t m_Npoints; + std::vector<std::uint64_t> &m_Points; + ///< C-to-C++ wrapper needs a pointer to hold the points created by the C + /// application + std::uint64_t *m_PointsC = nullptr; +}; + +} // namespace adios + +#endif /*__ADIOS_SELECTION_POINTS_H__*/ diff --git a/source/functions/adiosFunctions.cpp b/source/functions/adiosFunctions.cpp index 0946dc0d6..a24cc4c25 100644 --- a/source/functions/adiosFunctions.cpp +++ b/source/functions/adiosFunctions.cpp @@ -632,6 +632,17 @@ std::vector<int> CSVToVectorInt(const std::string csv) return numbers; } +void ConvertUint64VectorToSizetVector(const std::vector<std::uint64_t> &in, + std::vector<std::size_t> &out) +{ + out.clear(); + out.reserve(in.size()); + for (const auto inElement : in) + { + out.push_back(static_cast<std::size_t>(inElement)); + } +} + bool CheckBufferAllocation(const std::size_t newSize, const float growthFactor, const std::size_t maxBufferSize, std::vector<char> &buffer) -- GitLab