diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d70affa280c7e44ea14f36208a788d3c6841b73..89463224a89678ee16c84af00e469d88ec185054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,8 +72,10 @@ if(ADIOS_USE_MPI) endif() option(ADIOS_USE_BZip2 "Enable support for BZip2 transforms" OFF) option(ADIOS_USE_ADIOS1 "Enable support for the ADIOS 1 engine" OFF) -option(ADIOS_USE_DataMan "Enable support for the DataMan engine" OFF) -option(ADIOS_USE_PHDF5 "Enable support for hdf5" OFF) + +# DataMan is not a user-settable option. It will always be enabled if the +# platform supports it. +set(ADIOS_USE_DataMan ${SHARED_LIBS_SUPPORTED}) #------------------------------------------------------------------------------# # Third party libraries diff --git a/Contributing.md b/Contributing.md index 0348aa104ab0aedfc0070c6da3859fcd7c54351e..11e1daeec43cc22fa07abb30574c28be4b2b0728 100644 --- a/Contributing.md +++ b/Contributing.md @@ -3,10 +3,32 @@ This guide will walk you through how to submit changes to ADIOS and interact with the project as a developer. +Table of Contents +================= + + * [Contributor's Guide](#contributors-guide) + * [Table of Contents](#table-of-contents) + * [Workflow](#workflow) + * [Setup](#setup) + * [Making a change and submitting a pull request](#making-a-change-and-submitting-a-pull-request) + * [Create the topic branch](#create-the-topic-branch) + * [Do I need to merge master into my branch first?](#do-i-need-to-merge-master-into-my-branch-first) + * [Submit a pull request](#submit-a-pull-request) + * [Template implementation separation](#template-implementation-separation) + * [Example](#example) + * [Before separation of public and private template implementation](#before-separation-of-public-and-private-template-implementation) + * [Foo.h](#fooh-containing-all-implementation) + * [After separation of public and private template implementation](#after-separation-of-public-and-private-template-implementation) + * [Foo.h](#fooh-containing-only-prototypes-and-explicit-instantiation-declarations) + * [Foo.inl](#fooinl-containing-template-implementations-that-always-need-to-be-included) + * [Foo.tcc](#footcc-containing-template-implementations-that-should-be-restricted-to-only-known-types) + * [Foo.cpp](#foocpp-containing-non-template-implementations-and-explicit-instantiations-definitions-for-known-types) + * [Code formatting and style](#code-formatting-and-style) + ## Workflow ADIOS uses the GitHub fork-and-branch model. In this, the project "lives" in it's main repository located at https://github.com/ornladios/adios2.git, while each individual developer has their own copy of the repo to work in. Changes are then submitted to the main repository via pull-requests made with branches from your fork. -### Setup +## Setup To setup your local repository for development: 1. Fork the main repository on GitHub: @@ -49,10 +71,10 @@ Setting up git hooks... $ ``` -### Making a change and submitting a pull request +## Making a change and submitting a pull request At this point you are ready to get to work. The first thing to do is to create a branch. ADIOS uses a "branchy" workflow where all changes are committed through self-contained "topic branches". This helps ensure a clean traceable git history and reduce conflicts. -#### Create the topic branch +### Create the topic branch 1. Make sure you are starting from a current master: ``` @@ -79,7 +101,7 @@ Branch <your-topic-branch-name> set up to track remote branch <your-topic-branch $ ``` -##### Do I need to merge master into my branch first? +#### Do I need to merge master into my branch first? Not usually. The only time to do that is to resolve conflicts. You're pull request will be automatically rejected if merge-conflicts exist, in which case you can then resolve them by either re-basing your branch the current master (preferable): ``` $ git fetch --all -p @@ -95,7 +117,7 @@ $ git merge upstream/master $ git push -f ``` -#### Submit a pull request +### Submit a pull request 1. Log in to your GitHub fork. 2. You should see a message at the top that informs you of your recently pushed branch, something like: `<your-topic-branch-name> (2 minutes ago)`. On the right side, select the `[Compare & pull request]` button. 3. Fill in the appropriate information for the name of the branch and a brief summary of the changes it contains. @@ -104,14 +126,236 @@ $ git push -f You have now created a pull request (PR) that is pending several status checks before it can be merged. Currently, the only check being performed is for source code formatting and style. In the future, however, the will be a more in depth continuous integration system tied to the pull requests that tests for build and test failures every time a PR is submitted or updated. Once the status checks pass, the PR will be eligible for merging by one of the project maintainers. -### Code formatting and style +## Template implementation separation +The ADIOS C++ classes try to explicitly separate class declarations from their implementation. Typically this is done by having a separate .h and .cpp file, however it get's more complicated when templates are involved. To maintain the distinct separation between definition and implementation, we use explicit instantiation with 4 different source file types: +* ClassName.h + * The main header file containing *only* the class and member declarations with no implementation. This also contains the declarations for explicitly instantiated members. +* ClassName.inl + * A file containing inline function implementations that need to be made public. This is to be included at the bottom of ClassName.h and should *only* contain implementations that need to be made public. +* ClassName.tcc + * A file containing most of the template implementations that can be hidden through explicit instantiation. +* ClassName.cpp + * A file containing the non-template implementations and the explicit instation of any template members. + +### Example +Here is an example of a simple class `Foo` with template member functions `Bar1` and `Bar2` + +#### Before separation of public and private template implementation +##### Foo.h containing all implementation +```cpp +#ifndef FOO_H_ +#define FOO_H_ + +namespace adios +{ + +class Foo +{ +public: + Foo() + : m_Bar1Calls(0), m_Bar2Calls(0), m_Bar3Calls(0); + { + } + + virtual ~Foo() = default; + + template<typename T> + void Bar1() + { + Bar1Helper<T>(); + } + + template<typename T> + void Bar2() + { + Bar2Helper<T>(); + } + + void Bar3() + { + Bar3Helper(); + } + +private: + template<typename T> + void Bar1Helper() + { + ++m_Bar1Calls; + } + + template<typename T> + void Bar2Helper() + { + ++m_Bar2Calls; + } + + void Bar3Helper() + { + ++m_Bar3Calls; + } + + size_t m_Bar1Calls; + size_t m_Bar2Calls; + size_t m_Bar3Calls; +}; + +} // end namespace adios +#endif // FOO_H_ +``` + +#### After separation of public and private template implementation + +In this example, we want to hide the template implementation from the header. We will implement this such that `Bar1` is only callable from the core numeric types, i.e. ints, floats, and complex, while `Bar2` is callable from all types. This will necessitate that `Bar1` and it's helper function is implemented in a .tcc file with explicit instantiation for the allowed types while `Bar2` and it's helper function will need to be inlined in the .inl file to be accessible for all types. We will also use a helper macro ADIOS provides to iterate over the core numeric types for the explicit instantiation of `Bar1`. + +##### Foo.h containing only prototypes and explicit instantiation declarations +```cpp +#ifndef FOO_H_ +#define FOO_H_ + +#include "ADIOSMacros.h" + +namespace adios +{ +class Foo +{ +public: + Foo(); + virtual ~Foo() = default; + + template<typename T> + void Bar1(); + + template<typename T> + void Bar2(); + + void Bar3(); +private: + template<typename T> + void Bar1Helper(); + + template<typename T> + void Bar2Helper(); + + void Bar3Helper; + + size_t m_Bar1Calls; + size_t m_Bar2Calls; + size_t m_Bar3Calls; +}; + +// Create declarations for explicit instantiations +#define declare_explicit_instantiation(T) \ + extern template void Foo::Bar1<T>(); + +ADIOS_FOREACH_TYPE_1ARG(declare_explicit_instantiation) +#undef(declare_explicit_instantiation) +} // end namespace adios + +#include "Foo.inl" +#endif // FOO_H_ +``` +Note here that Bar1Helper does not need an explicit instantiation because it's not a visible funtion in the callable interface. It's implementaion will be available to Bar1 inside the tcc file where it's called from. + +##### Foo.inl containing template implementations that always need to be included +```cpp +#ifndef FOO_INL_ +#define FOO_INL_ +#ifndef FOO_H_ +#error "Inline file should only be included from it's header, never on it's own" +#endif + +// No need to include Foo.h since it's where this is include from + +namespace adios +{ + +template<typename T> +void Foo::Bar2() +{ + Bar2Helper<T>(); +} + +template<typename T> +void Foo::Bar2Helper() +{ + ++m_Bar2Calls; +} + +} // end namespace adios + +#endif // FOO_INL_ +``` + +##### Foo.tcc containing template implementations that should be restricted to only known types +```cpp +#ifndef FOO_TCC_ +#define FOO_TCC_ + +#include "Foo.h" +namespace adios +{ + +template<typename T> +void Foo::Bar1() +{ + Bar1Helper<T>(); +} + +template<typename T> +void Foo::Bar1Helper() +{ + ++m_Bar1Calls; +} + +} // end namespace adios + +#endif // FOO_TCC_ +``` + +##### Foo.cpp containing non-template implementations and explicit instantiations definitions for known types. +```cpp +#include "Foo.h" +#include "Foo.tcc" + +namespace adios +{ + +Foo::Foo() +: m_Bar1Calls(0), m_Bar2Calls(0), m_Bar3Calls(0) +{ +} + +void Foo::Bar3() +{ + Bar3Helper(); +} + +void Foo::Bar3Helper() +{ + ++m_Bar3Calls; +} + +// Create explicit instantiations of existing definitions +#define define_explicit_instantiation(T) \ + template void Foo::Bar1<T>(); + +ADIOS_FOREACH_TYPE_1ARG(define_explicit_instantiation) +#undef(define_explicit_instantiation) + +} // end namespace adios +``` + +## Code formatting and style ADIOS uses the clang-format tool to automatically enforce source code style and formatting rules. There are various ways to integrate the clang-format tool into your IDE / Code Editor depending on if you use Emacs, Vim, Eclipse, KDevelop, Microsoft Visual Studio, etc. that are a bit outside the scope of this document but a quick google search for "integrate <insert-editor-here> clang-format" should point you in the right direction. However, you can always reformat the code manually by running: ``` clang-format -i SourceFile.cpp SourceFile.h ``` That will apply the formatting rules used by the ADIOS project. + +While some of the formatting rules are fairly detailed, the main points are: + 1. Lines no longer than 80 characters. 1. Always use braces { and }, even for 1 line if blocks. 1. Use 4 spaces for indentation. -There are more formatting rules but these three should at least get you close and prevent any drastic re-writes from the re-formatting tools. More details can be found by looking at the .clang-format config file n the root of the repository and by looking at the clang-format documentation http://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html. While the formatting rules are a bit more involved, the main points are: +There are more formatting rules but these three should at least get you close and prevent any drastic re-writes from the re-formatting tools. More details can be found by looking at the .clang-format config file in the root of the repository and by looking at the clang-format documentation http://releases.llvm.org/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html. diff --git a/cmake/FindDataMan.cmake b/cmake/FindDataMan.cmake deleted file mode 100644 index fd9ce61b5f48f8db808983bb637cf1aa04e4a153..0000000000000000000000000000000000000000 --- a/cmake/FindDataMan.cmake +++ /dev/null @@ -1,71 +0,0 @@ -#------------------------------------------------------------------------------# -# Distributed under the OSI-approved Apache License, Version 2.0. See -# accompanying file Copyright.txt for details. -#------------------------------------------------------------------------------# -# -# FindDataMan -# --------- -# -# Try to find the DataMan library from Jason Wang, ORNL -# https://github.com/JasonRuonanWang/DataMan -# -# This module defines the following variables: -# -# DataMan_FOUND - System has DataMan -# DataMan_INCLUDE_DIRS - The DataMan include directory -# DataMan_LIBRARIES - Link these to use DataMan -# -# and the following imported targets: -# DataMan::DataMan - The core DataMan library -# -# You can also set the following variable to help guide the search: -# DataMan_ROOT_DIR - The install prefix for DataMan containing the -# include and lib folders -# Note: this can be set as a CMake variable or an -# environment variable. If specified as a CMake -# variable, it will override any setting specified -# as an environment variable. - -if(NOT DataMan_FOUND) - if((NOT DataMan_ROOT_DIR) AND (NOT (ENV{DataMan_ROOT_DIR} STREQUAL ""))) - set(DataMan_ROOT_DIR "$ENV{DataMan_ROOT_DIR}") - endif() - - # Search for the core libraries - if(DataMan_ROOT_DIR) - # If a root directory is specified, then don't look anywhere else - find_path(DataMan_INCLUDE_DIR DataMan.h - HINTS ${DataMan_ROOT_DIR}/include - NO_DEFAULT_PATHS - ) - set(_DataMan_LIBRARY_HINT HINTS ${DataMan_ROOT_DIR}/lib NO_DEFAULT_PATHS) - else() - # Otherwise use the include dir as a basis to search for the lib - find_path(DataMan_INCLUDE_DIR DataMan.h) - if(DataMan_INCLUDE_DIR) - get_filename_component(_DataMan_PREFIX "${DataMan_INCLUDE_DIR}" PATH) - set(_DataMan_LIBRARY_HINT HINTS ${_DataMan_PREFIX}/lib) - unset(_DataMan_PREFIX) - endif() - endif() - find_library(DataMan_LIBRARY dataman ${_DataMan_LIBRARY_HINT}) - unset(_DataMan_LIBRARY_HINT) - - find_package_handle_standard_args(DataMan - FOUND_VAR DataMan_FOUND - REQUIRED_VARS - DataMan_INCLUDE_DIR - DataMan_LIBRARY - ) - if(DataMan_FOUND) - set(DataMan_INCLUDE_DIRS ${DataMan_INCLUDE_DIR}) - set(DataMan_LIBRARIES ${DataMan_LIBRARY}) - if(DataMan_FOUND AND NOT TARGET DataMan::DataMan) - add_library(DataMan::DataMan UNKNOWN IMPORTED) - set_target_properties(DataMan::DataMan PROPERTIES - IMPORTED_LOCATION "${DataMan_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${DataMan_INCLUDE_DIR}" - ) - endif() - endif() -endif() diff --git a/doc/API_design/API_example_use.cpp b/doc/API_design/API_example_use.cpp index a35146935cf564dea610accee6ad67efdfbe6ce6..701bb8994bf973330fb61381b2d2d5fa84741563 100644 --- a/doc/API_design/API_example_use.cpp +++ b/doc/API_design/API_example_use.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) // Global class/object that serves for init, finalize and provides ADIOS // functions - adios::ADIOS adios("config.xml", comm, /*verbose=*/adios::INFO, + adios::ADIOS adios("config.xml", comm, /*verbose=*/adios::Verbose::INFO, /*debugflag=*/false); /************* @@ -83,8 +83,8 @@ int main(int argc, char *argv[]) "Ragged", adios::Dims{nproc, adios::VARYING_DIMENSION}); // ragged array // add transform to variable - adios::Transform zfp = adios::transform::ZFP(); - var2D.AddTransform(zfp, "accuracy=0.001"); + adios::Transform compress = adios::transform::BZip2(); + var2D.AddTransform(compress, "level=5"); // open...write.write.write...advance...write.write.write...advance... // ...close cycle @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) // write and // its offsets in the global spaces. This could have been done in // adios.DefineVariable() - adios::Selection sel = adios.SelectionBoundingBox( + adios::SelectionBoundingBox sel = adios::SelectionBoundingBox( {1, NX}, {rank, NX}); // local dims and offsets; both as list var2D.SetSelection( sel); // Shall we call it SetSpaceSelection, SetOutputSelection? @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) // Size of the bounding box should match the // "space" selection which was given above. Default memspace is the full // selection. - adios::Selection memspace = adios.SelectionBoundingBox( + adios::SelectionBoundingBox memspace = adios::SelectionBoundingBox( {1, NX}, {0, 1}); // local dims and offsets; both as list var2D.SetMemorySelection(memspace); @@ -226,10 +226,10 @@ int main(int argc, char *argv[]) // we // READ and // its offsets in the global spaces - adios::Selection bbsel = adios.SelectionBoundingBox( + adios::SelectionBoundingBox bbsel = adios::SelectionBoundingBox( {1, NX}, {0, 0}); // local dims and offsets; both as list var2D.SetSelection(bbsel); - adios::Selection memspace = adios.SelectionBoundingBox( + adios::SelectionBoundingBox memspace = adios::SelectionBoundingBox( {1, NX}, {0, 1}); // local dims and offsets; both as list var2D.SetMemorySelection(memspace); reader->Read<double>(var2D, *Temperature); @@ -292,9 +292,9 @@ int main(int argc, char *argv[]) // we // READ and // its offsets in the global spaces if we know this somehow - adios::Selection bbsel = adios.SelectionBoundingBox( + adios::SelectionBoundingBox bbsel = adios::SelectionBoundingBox( {1, NX}, {0, 0}); // local dims and offsets; both as list - var2D->SetSelection(bbsel); + var2D.SetSelection(bbsel); reader->Read<double>(var2D, *Temperature); // Let ADIOS allocate space for the incoming (per-writer) item @@ -399,7 +399,7 @@ int main(int argc, char *argv[]) // Open a file with all steps immediately available std::shared_ptr<adios::Engine> reader = adios.OpenFileReader( - "filename.bp", comm, rmethod, adios::COLLECTIVE_IO); + "filename.bp", comm, rmethod, adios::IOMode::COLLECTIVE); /* NX */ /* There is a single value for each step. We can read all into a 1D diff --git a/examples/heatTransfer/IO_adios2.cpp b/examples/heatTransfer/IO_adios2.cpp deleted file mode 100644 index aea0493ca7dfbbea62f9568f63c4a289bbaa1bba..0000000000000000000000000000000000000000 --- a/examples/heatTransfer/IO_adios2.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * IO_ADIOS2.cpp - * - * Created on: Feb 2017 - * Author: Norbert Podhorszki - */ - -#include "IO.h" -#include "ADIOS_CPP.h" - -#include <string> - -static int rank_saved; -adios::ADIOS *ad = nullptr; -std::shared_ptr<adios::Engine> bpWriter; -adios::Variable<double> *varT = nullptr; - -IO::IO(const Settings &s, MPI_Comm comm) -{ - rank_saved = s.rank; - m_outputfilename = s.outputfile + ".bp"; - ad = new adios::ADIOS("adios2.xml", comm, adios::Verbose::INFO); - - // Define method for engine creation - // 1. Get method def from config file or define new one - - adios::Method &bpWriterSettings = ad->DeclareMethod("output"); - if (!bpWriterSettings.IsUserDefined()) - { - // if not defined by user, we can change the default settings - bpWriterSettings.SetEngine("BP"); // BP is the default engine - bpWriterSettings.AllowThreads( - 1); // allow 1 extra thread for data processing - bpWriterSettings.AddTransport( - "File", "lucky=yes"); // ISO-POSIX file is the default transport - // Passing parameters to the transport - bpWriterSettings.SetParameters( - "have_metadata_file", - "yes"); // Passing parameters to the engine - bpWriterSettings.SetParameters( - "Aggregation", - std::to_string((s.nproc + 1) / 2)); // number of aggregators - } - - // 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 - ); - - // add transform to variable - // adios::Transform tr = adios::transform::BZIP2( ); - // varT.AddTransform( tr, "" ); - // varT.AddTransform( tr,"accuracy=0.001" ); // for ZFP - - bpWriter = ad->Open(m_outputfilename, "w", comm, bpWriterSettings); - - // ad->Open(m_outputfilename, "w", comm, bpWriterSettings); - - if (bpWriter == nullptr) - throw std::ios_base::failure("ERROR: failed to open ADIOS bpWriter\n"); -} - -IO::~IO() -{ - bpWriter->Close(); - 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) -{ - /* 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 - // 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); - - /* Select the area that we want to write from the data pointer we pass to - the - writer. - Think HDF5 memspace, just not hyperslabs, only a bounding box selection. - Engine will copy this bounding box from the data pointer into the output - buffer. - Size of the bounding box should match the "space" selection which was - given - above. - Default memspace is always the full selection. - */ - adios::Selection memspace = - adios.SelectionBoundingBox({s.ndx, s.ndy}, {1, 1}); - var2D.SetMemorySelection(memspace); - - bpWriter->Write<double>(*varT, ht.data()); - bpWriter->Advance(); -} diff --git a/examples/heatTransfer/write/IO_adios2.cpp b/examples/heatTransfer/write/IO_adios2.cpp index 72d118ea15748e2d9852879ccc7f519f184ba72f..0f0c06bb795e0972564d8f5884b52955a08207c9 100644 --- a/examples/heatTransfer/write/IO_adios2.cpp +++ b/examples/heatTransfer/write/IO_adios2.cpp @@ -31,12 +31,13 @@ IO::IO(const Settings &s, MPI_Comm comm) if (!bpWriterSettings.IsUserDefined()) { // if not defined by user, we can change the default settings - bpWriterSettings.SetEngine("BPFileWriter"); // BP is the default engine - bpWriterSettings.AllowThreads(1); // for data processing - - bpWriterSettings.AddTransport( - "File", "lucky=yes"); // ISO-POSIX file is the default transport - // Passing parameters to the transport + // BPFileWriter is the default engine + bpWriterSettings.SetEngine("BPFileWriter"); + // Allow an extra thread for data processing + bpWriterSettings.AllowThreads(1); + // ISO-POSIX file is the default transport + // Passing parameters to the transport + bpWriterSettings.AddTransport("File", "lucky=yes"); const std::string aggregatorsParam("Aggregators=" + std::to_string((s.nproc + 1) / 2)); diff --git a/examples/hello/adios1Writer/helloADIOS1Writer.cpp b/examples/hello/adios1Writer/helloADIOS1Writer.cpp index 87101533b4795379e3b2c94966c44d01fea83403..fc6064b27b8fa5ee50be1a86f9c1b001a3227684 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer.cpp @@ -64,10 +64,10 @@ int main(int argc, char *argv[]) // Define method for engine creation, it is basically straight-forward // parameters - adios::Method &bpWriterSettings = adios.DeclareMethod( - "SingleFile"); // default method type is BPWriter + adios::Method &bpWriterSettings = adios.DeclareMethod("hello"); bpWriterSettings.SetEngine("ADIOS1Writer"); bpWriterSettings.SetParameters("profile_units=mus"); + bpWriterSettings.SetIOMode(adios::IOMode::COLLECTIVE); bpWriterSettings.AddTransport( "File", "profile_units=mus", "have_metadata_file=no"); // uses default POSIX library @@ -75,8 +75,7 @@ int main(int argc, char *argv[]) // Create engine smart pointer due to polymorphism, // Open returns a smart pointer to Engine containing the Derived class // Writer - auto bpWriter = adios.Open("myDoubles.bp", "w", bpWriterSettings, - adios::IOMode::COLLECTIVE); + auto bpWriter = adios.Open("myDoubles.bp", "w", bpWriterSettings); if (bpWriter == nullptr) throw std::ios_base::failure( diff --git a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp index 5955b33436df32cd835391a75c85bf2bc8f7f53b..2b850253a997c94106cd472043f05d4e7050372e 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp @@ -42,8 +42,8 @@ int main(int argc, char *argv[]) // Define method for engine creation, it is basically straight-forward // parameters - adios::Method &bpWriterSettings = adios.DeclareMethod( - "SinglePOSIXFile"); // default method type is Writer + adios::Method &bpWriterSettings = adios.DeclareMethod("hello"); + bpWriterSettings.SetIOMode(adios::IOMode::COLLECTIVE); bpWriterSettings.SetParameters("profile_units=mus"); bpWriterSettings.AddTransport("File", "have_metadata_file=yes", "profile_units=mus"); @@ -52,8 +52,7 @@ int main(int argc, char *argv[]) // Open returns a smart pointer to Engine containing the Derived class // Writer auto bpFileWriter = - adios.Open("myDoubles_nompi.bp", "w", bpWriterSettings, - adios::IOMode::COLLECTIVE); + adios.Open("myDoubles_nompi.bp", "w", bpWriterSettings); if (bpFileWriter == nullptr) throw std::ios_base::failure( diff --git a/examples/hello/datamanReader/helloDataManReader.cpp b/examples/hello/datamanReader/helloDataManReader.cpp index 6c1c87897cd7f8bfef280a045586d5c94131d195..07a0099153c2b21b9dd2b54254f156ad5265fa4b 100644 --- a/examples/hello/datamanReader/helloDataManReader.cpp +++ b/examples/hello/datamanReader/helloDataManReader.cpp @@ -46,16 +46,16 @@ int main(int argc, char *argv[]) // Define method for engine creation, it is basically straight-forward // parameters adios::Method &datamanSettings = adios.DeclareMethod("WAN"); - if (!datamanSettings.isUserDefined()) + if (!datamanSettings.IsUserDefined()) { // if not defined by user, we can change the default settings datamanSettings.SetEngine("DataManReader"); datamanSettings.SetParameters("peer-to-peer=yes"); - datamanSettings.AddTransport("Mdtm", "localIP=128.0.0.0.1", - "remoteIP=128.0.0.0.2", + datamanSettings.AddTransport("Mdtm", "localIP=127.0.0.1", + "remoteIP=127.0.0.1", "tolerances=1,2,3"); - // datamanSettings.AddTransport( "ZeroMQ", "localIP=128.0.0.0.1.1", - // "remoteIP=128.0.0.0.2.1", "tolerances=1,2,3" ); not yet supported + // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1", + // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported // , // will throw an exception } @@ -64,8 +64,7 @@ int main(int argc, char *argv[]) // polymorphism, // Open returns a smart pointer to Engine containing the Derived class // DataManReader - auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings, - adios::IOMode::INDEPENDENT); + auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings); if (datamanReader == nullptr) throw std::ios_base::failure( diff --git a/examples/hello/datamanReader/helloDataManReader_nompi.cpp b/examples/hello/datamanReader/helloDataManReader_nompi.cpp index db7a717be43dbfe7809d1dbcc21f3645c03eda5d..cb406b450f24970146d0fcc6f4a6e270baea18f7 100644 --- a/examples/hello/datamanReader/helloDataManReader_nompi.cpp +++ b/examples/hello/datamanReader/helloDataManReader_nompi.cpp @@ -39,18 +39,16 @@ int main(int argc, char *argv[]) // Define method for engine creation, it is basically straight-forward // parameters adios::Method &datamanSettings = adios.DeclareMethod("WAN"); - if (!datamanSettings.isUserDefined()) + if (!datamanSettings.IsUserDefined()) { // if not defined by user, we can change the default settings datamanSettings.SetEngine("DataManReader"); - datamanSettings.SetParameters( - "real_time=yes", "method_type=stream", "method=zmq", - "local_ip=127.0.0.1", "remote_ip=127.0.0.1", "local_port=12307", - "remote_port=12306"); - // datamanSettings.AddTransport( "Mdtm", "localIP=128.0.0.0.1", - // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" ); - // datamanSettings.AddTransport( "ZeroMQ", "localIP=128.0.0.0.1.1", - // "remoteIP=128.0.0.0.2.1", "tolerances=1,2,3" ); not yet supported + datamanSettings.SetParameters("real_time=yes", "method_type=stream", + "method=dump"); + // datamanSettings.AddTransport( "Mdtm", "localIP=127.0.0.1", + // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); + // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1", + // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported // , // will throw an exception } @@ -59,8 +57,7 @@ int main(int argc, char *argv[]) // polymorphism, // Open returns a smart pointer to Engine containing the Derived class // DataManReader - auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings, - adios::IOMode::INDEPENDENT); + auto datamanReader = adios.Open("myDoubles.bp", "r", datamanSettings); if (datamanReader == nullptr) throw std::ios_base::failure( @@ -68,8 +65,9 @@ int main(int argc, char *argv[]) datamanReader->SetCallBack(getcb); - while (1) + for (int i = 0; i < 3; i++) { + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } adios::Variable<double> *ioMyDoubles = diff --git a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp index fa7158c37011db4a33088b714a925627348cb925..aa2aed47a3ae5779ba7cbe7155b2245d32284f44 100644 --- a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp +++ b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp @@ -52,10 +52,10 @@ int main(int argc, char *argv[]) "real_time=yes", "method_type=stream", "method=dump", "monitoring=yes", "local_ip=127.0.0.1", "remote_ip=127.0.0.1", "local_port=12306", "remote_port=12307"); - // datamanSettings.AddTransport( "Mdtm", "localIP=128.0.0.0.1", - // "remoteIP=128.0.0.0.2", "tolerances=1,2,3" ); - // datamanSettings.AddTransport( "ZeroMQ", "localIP=128.0.0.0.1.1", - // "remoteIP=128.0.0.0.2.1", "tolerances=1,2,3" ); not yet supported + // datamanSettings.AddTransport( "Mdtm", "localIP=127.0.0.1", + // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); + // datamanSettings.AddTransport( "ZeroMQ", "localIP=127.0.0.1", + // "remoteIP=127.0.0.1", "tolerances=1,2,3" ); not yet supported // , // will throw an exception } diff --git a/include/ADIOS.h b/include/ADIOS.h index e389c9bdd42a5eaa18342dbfb8b4dccb0d5d40a0..b23d310c9caf03e6ddbe4f0fb9752d6f8123d520 100644 --- a/include/ADIOS.h +++ b/include/ADIOS.h @@ -275,20 +275,19 @@ protected: // no const to allow default empty and copy constructors std::map<unsigned int, Variable<std::complex<long double>>> m_CLDouble; std::map<unsigned int, VariableCompound> m_Compound; - std::string m_ConfigFile; ///< XML File to be read containing configuration - /// information - bool m_DebugMode = false; ///< if true will do more checks, exceptions, - /// warnings, expect slower code + ///< XML File to be read containing configuration information + std::string m_ConfigFile; + + ///< if true will do more checks, exceptions, warnings, expect slower code + bool m_DebugMode = false; // Variables - std::map<std::string, std::pair<std::string, unsigned int>> - m_Variables; ///< Makes variable name unique, key: variable name, - /// value: - /// pair.first = type, pair.second = index in corresponding - /// vector of Variable + ///< Makes variable name unique, key: variable name,value: pair.first = + /// type, pair.second = index in corresponding vector of Variable + std::map<std::string, std::pair<std::string, unsigned int>> m_Variables; - std::vector<std::shared_ptr<Transform>> - m_Transforms; ///< transforms associated with ADIOS run + ///< transforms associated with ADIOS run + std::vector<std::shared_ptr<Transform>> m_Transforms; /** * @brief List of Methods (engine metadata) defined from either ADIOS XML @@ -299,8 +298,9 @@ protected: // no const to allow default empty and copy constructors * </pre> */ std::map<std::string, Method> m_Methods; - std::set<std::string> m_EngineNames; ///< set used to check Engine name - /// uniqueness in debug mode + + ///< set used to check Engine name uniqueness in debug mode + std::set<std::string> m_EngineNames; /** * @brief Checks for group existence in m_Groups, if failed throws @@ -343,19 +343,22 @@ protected: // no const to allow default empty and copy constructors std::map<unsigned int, Variable<T>> &GetVariableMap(); }; +//------------------------------------------------------------------------------ + // Explicit declaration of the template methods #define declare_template_instantiation(T) \ extern template Variable<T> &ADIOS::DefineVariable<T>( \ const std::string &name, const Dims, const Dims, const Dims); \ - extern template Variable<T> &ADIOS::GetVariable<T>(const std::string &); \ - extern template unsigned int ADIOS::GetVariableIndex<T>( \ - const std::string &name); \ - template <> \ - std::map<unsigned int, Variable<T>> &ADIOS::GetVariableMap<T>(); + \ + extern template Variable<T> &ADIOS::GetVariable<T>(const std::string &); + ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation) extern template unsigned int ADIOS::GetVariableIndex<void>(const std::string &); #undef declare_template_instantiation } // end namespace adios +// Include the inline implementations for the public interface +#include "ADIOS.inl" + #endif /* ADIOS_H_ */ diff --git a/include/ADIOS.tcc b/include/ADIOS.inl similarity index 85% rename from include/ADIOS.tcc rename to include/ADIOS.inl index de230eef77a0449d2bfb4d65cb8253117c878995..1efaa8380b55342433a2f8973191afd26d96e996 100644 --- a/include/ADIOS.tcc +++ b/include/ADIOS.inl @@ -6,10 +6,11 @@ * This contains the template implementations for the ADIOS class */ -#ifndef ADIOS_TCC_ -#define ADIOS_TCC_ - -#include "ADIOS.h" +#ifndef ADIOS_INL_ +#define ADIOS_INL_ +#ifndef ADIOS_H_ +#error "Inline file should only be included from it's header, never on it's own" +#endif namespace adios { @@ -31,4 +32,4 @@ VariableCompound &ADIOS::DefineVariableCompound(const std::string &name, } // end namespace adios -#endif /* ADIOS_TCC_ */ +#endif /* ADIOS_INL_ */ diff --git a/include/ADIOSMacros.h b/include/ADIOSMacros.h index 54f8492e9e49f16797d5e52a46e3c0e86d0da600..06dd9cd3b4167a21a2b0f73de1a61bebe45ab5ed 100644 --- a/include/ADIOSMacros.h +++ b/include/ADIOSMacros.h @@ -39,4 +39,24 @@ MACRO(std::complex<double>) \ MACRO(std::complex<long double>) +#define ADIOS_FOREACH_PRIMITIVE_TYPE_1ARG(MACRO) \ + MACRO(char) \ + MACRO(unsigned char) \ + MACRO(short) \ + MACRO(unsigned short) \ + MACRO(int) \ + MACRO(unsigned int) \ + MACRO(long int) \ + MACRO(unsigned long int) \ + MACRO(long long int) \ + MACRO(unsigned long long int) \ + MACRO(float) \ + MACRO(double) \ + MACRO(long double) + +#define ADIOS_FOREACH_COMPLEX_TYPE_1ARG(MACRO) \ + MACRO(float) \ + MACRO(double) \ + MACRO(long double) + #endif // ADIOSMACROS_H diff --git a/include/ADIOSTypes.h b/include/ADIOSTypes.h index a3e286d943cff87ecacae3dea7cfb58c636be47f..585a7f680bb1d6df7de6e15fe620363e80b5e13e 100644 --- a/include/ADIOSTypes.h +++ b/include/ADIOSTypes.h @@ -11,6 +11,11 @@ #ifndef ADIOS_TYPES_H_ #define ADIOS_TYPES_H_ +#include <complex> +#include <cstddef> +#include <cstdint> +#include <type_traits> + namespace adios { @@ -37,6 +42,99 @@ enum class IOMode COLLECTIVE = 1 }; -} // end namespace +// Alias the fixed sized typed into the adios namespace to make sure we're +// always using the right ones. +using std::size_t; + +using std::int8_t; +using std::uint8_t; +using std::int16_t; +using std::uint16_t; +using std::int32_t; +using std::uint32_t; +using std::int64_t; +using std::uint64_t; + +// Not sure if we're really use these ones but we'll round it out for +// completion +using real32_t = float; +using real64_t = double; +using complex32_t = std::complex<real32_t>; +using complex64_t = std::complex<real64_t>; + +// Get a fixed width integer type from a size specification +template <size_t Bytes, bool Signed> +struct FixedWidthInt; + +template <> +struct FixedWidthInt<1, true> +{ + using Type = std::int8_t; +}; +template <> +struct FixedWidthInt<2, true> +{ + using Type = std::int16_t; +}; +template <> +struct FixedWidthInt<4, true> +{ + using Type = std::int32_t; +}; +template <> +struct FixedWidthInt<8, true> +{ + using Type = std::int64_t; +}; +template <> +struct FixedWidthInt<1, false> +{ + using Type = std::uint8_t; +}; +template <> +struct FixedWidthInt<2, false> +{ + using Type = std::uint16_t; +}; +template <> +struct FixedWidthInt<4, false> +{ + using Type = std::uint32_t; +}; +template <> +struct FixedWidthInt<8, false> +{ + using Type = std::uint64_t; +}; + +// Some core type information that may be useful at compile time +template <typename T, typename Enable = void> +struct TypeInfo; + +template <typename T> +struct TypeInfo<T, typename std::enable_if<std::is_integral<T>::value>::type> +{ + using IOType = + typename FixedWidthInt<sizeof(T), std::is_signed<T>::value>::Type; + using ValueType = T; +}; + +template <typename T> +struct TypeInfo<T, + typename std::enable_if<std::is_floating_point<T>::value>::type> +{ + using IOType = T; + using ValueType = T; +}; + +template <typename T> +struct TypeInfo<T, typename std::enable_if<std::is_same< + T, std::complex<typename T::value_type>>::value>::type> +{ + using IOType = T; + using ValueType = typename T::value_type; +}; + +} // end namespace adios #endif /* ADIOS_TYPES_H_ */ diff --git a/include/core/Method.h b/include/core/Method.h index dc40806126f6da99aac4cc03be2479c62f00eecc..e2f06a6f4857348cdbfcff10e7b3c9fad74f48a5 100644 --- a/include/core/Method.h +++ b/include/core/Method.h @@ -48,7 +48,6 @@ public: /// unsafe std::string m_Type; ///< Method's engine type unsigned int m_nThreads = 1; - adios::IOMode m_IOMode = adios::IOMode::INDEPENDENT; std::map<std::string, std::string> m_Parameters; ///< method parameters std::vector<std::map<std::string, std::string>> @@ -78,6 +77,12 @@ public: */ void SetEngine(const std::string type); + /** + * Set the IO mode (collective or independent) + * @param IO mode + */ + void SetIOMode(const IOMode mode); + /** * Set how many threads the engine can use for its operations (e.g. file io, * compression, staging). @@ -135,6 +140,7 @@ public: private: Verbose m_Verbose = Verbose::WARN; + adios::IOMode m_IOMode = adios::IOMode::INDEPENDENT; void AddTransportParameters(const std::string type, const std::vector<std::string> ¶meters); diff --git a/include/engine/adios1/ADIOS1Reader.h b/include/engine/adios1/ADIOS1Reader.h index 53fb32bec3f8cf8c09ef7584c4f06213ed47bfba..baf55f4166b70ef934b077de1d79e569cc43ed3b 100644 --- a/include/engine/adios1/ADIOS1Reader.h +++ b/include/engine/adios1/ADIOS1Reader.h @@ -101,6 +101,8 @@ public: private: void Init(); ///< called from constructor, gets the selected ADIOS1 /// transport method from settings + void InitParameters(); + void InitTransports(); template <class T> Variable<T> *InquireVariableCommon(const std::string &name, diff --git a/include/engine/dataman/DataManReader.h b/include/engine/dataman/DataManReader.h index 6ed82a5982071e80bcb19e30426ac8f4acad0ba8..f29494f45ca7441c46c039ebfbd5d9115d41f19d 100644 --- a/include/engine/dataman/DataManReader.h +++ b/include/engine/dataman/DataManReader.h @@ -19,7 +19,7 @@ // supported capsules #include "capsule/heap/STLVector.h" -#include "DataManager.h" +#include "utilities/realtime/dataman/DataMan.h" namespace adios { @@ -38,11 +38,12 @@ public: * @param debugMode * @param nthreads */ - DataManReader(ADIOS &adios, const std::string name, + using json = nlohmann::json; + DataManReader(ADIOS &adios, const std::string &name, const std::string accessMode, MPI_Comm mpiComm, const Method &method); - ~DataManReader(); + virtual ~DataManReader() = default; /** * Set callback function from user application @@ -53,40 +54,40 @@ public: std::string, Dims)> callback); - Variable<void> *InquireVariable(const std::string name, + Variable<void> *InquireVariable(const std::string &name, const bool readIn = true); - Variable<char> *InquireVariableChar(const std::string name, + Variable<char> *InquireVariableChar(const std::string &name, const bool readIn = true); - Variable<unsigned char> *InquireVariableUChar(const std::string name, + Variable<unsigned char> *InquireVariableUChar(const std::string &name, const bool readIn = true); - Variable<short> *InquireVariableShort(const std::string name, + Variable<short> *InquireVariableShort(const std::string &name, const bool readIn = true); - Variable<unsigned short> *InquireVariableUShort(const std::string name, + Variable<unsigned short> *InquireVariableUShort(const std::string &name, const bool readIn = true); - Variable<int> *InquireVariableInt(const std::string name, + Variable<int> *InquireVariableInt(const std::string &name, const bool readIn = true); - Variable<unsigned int> *InquireVariableUInt(const std::string name, + Variable<unsigned int> *InquireVariableUInt(const std::string &name, const bool readIn = true); - Variable<long int> *InquireVariableLInt(const std::string name, + Variable<long int> *InquireVariableLInt(const std::string &name, const bool readIn = true); - Variable<unsigned long int> *InquireVariableULInt(const std::string name, + Variable<unsigned long int> *InquireVariableULInt(const std::string &name, const bool readIn = true); - Variable<long long int> *InquireVariableLLInt(const std::string name, + Variable<long long int> *InquireVariableLLInt(const std::string &name, const bool readIn = true); Variable<unsigned long long int> * - InquireVariableULLInt(const std::string name, const bool readIn = true); - Variable<float> *InquireVariableFloat(const std::string name, + InquireVariableULLInt(const std::string &name, const bool readIn = true); + Variable<float> *InquireVariableFloat(const std::string &name, const bool readIn = true); - Variable<double> *InquireVariableDouble(const std::string name, + Variable<double> *InquireVariableDouble(const std::string &name, const bool readIn = true); - Variable<long double> *InquireVariableLDouble(const std::string name, + Variable<long double> *InquireVariableLDouble(const std::string &name, const bool readIn = true); Variable<std::complex<float>> * - InquireVariableCFloat(const std::string name, const bool readIn = true); + InquireVariableCFloat(const std::string &name, const bool readIn = true); Variable<std::complex<double>> * - InquireVariableCDouble(const std::string name, const bool readIn = true); + InquireVariableCDouble(const std::string &name, const bool readIn = true); Variable<std::complex<long double>> * - InquireVariableCLDouble(const std::string name, const bool readIn = true); + InquireVariableCLDouble(const std::string &name, const bool readIn = true); /** * Not implemented @@ -94,7 +95,7 @@ public: * @param readIn * @return */ - VariableCompound *InquireVariableCompound(const std::string name, + VariableCompound *InquireVariableCompound(const std::string &name, const bool readIn = true); void Close(const int transportIndex = -1); @@ -108,7 +109,7 @@ private: /// m_Transports bool m_DoRealTime = false; - DataManager m_Man; + realtime::DataMan m_Man; std::function<void(const void *, std::string, std::string, std::string, Dims)> m_CallBack; ///< call back function diff --git a/include/engine/dataman/DataManWriter.h b/include/engine/dataman/DataManWriter.h index ec2392cf702cea65413f889fae38688e139888a2..9902afb02c249eb95d762a9008352e6502ad1101 100644 --- a/include/engine/dataman/DataManWriter.h +++ b/include/engine/dataman/DataManWriter.h @@ -20,7 +20,7 @@ // supported capsules #include "capsule/heap/STLVector.h" -#include "DataManager.h" //here comes your DataMan header +#include "utilities/realtime/dataman/DataMan.h" namespace adios { @@ -29,6 +29,7 @@ class DataManWriter : public Engine { public: + using json = nlohmann::json; /** * Constructor for dataman engine Writer for WAN communications * @param adios @@ -43,7 +44,7 @@ public: const std::string accessMode, MPI_Comm mpiComm, const Method &method); - ~DataManWriter(); + virtual ~DataManWriter() = default; void SetCallBack(std::function<void(const void *, std::string, std::string, std::string, Dims)> @@ -106,7 +107,7 @@ private: bool m_DoRealTime = false; bool m_DoMonitor = false; - DataManager m_Man; + realtime::DataMan m_Man; std::function<void(const void *, std::string, std::string, std::string, Dims)> m_CallBack; ///< call back function @@ -142,13 +143,13 @@ private: jmsg["doid"] = m_Name; jmsg["var"] = variable.m_Name; jmsg["dtype"] = GetType<T>(); - jmsg["putshape"] = variable.m_Dimensions; + jmsg["putshape"] = variable.m_LocalDimensions; if (variable.m_GlobalDimensions.size() == 0) - variable.m_GlobalDimensions = variable.m_Dimensions; + variable.m_GlobalDimensions = variable.m_LocalDimensions; jmsg["varshape"] = variable.m_GlobalDimensions; - if (variable.m_GlobalOffsets.size() == 0) - variable.m_GlobalOffsets.assign(variable.m_Dimensions.size(), 0); - jmsg["offset"] = variable.m_GlobalOffsets; + if (variable.m_Offsets.size() == 0) + variable.m_Offsets.assign(variable.m_LocalDimensions.size(), 0); + jmsg["offset"] = variable.m_Offsets; jmsg["timestep"] = 0; m_Man.put(values, jmsg); @@ -156,10 +157,11 @@ private: { MPI_Barrier(m_MPIComm); std::cout << "I am hooked to the DataMan library\n"; - std::cout << "putshape " << variable.m_Dimensions.size() << endl; + std::cout << "putshape " << variable.m_LocalDimensions.size() + << std::endl; std::cout << "varshape " << variable.m_GlobalDimensions.size() - << endl; - std::cout << "offset " << variable.m_GlobalOffsets.size() << endl; + << std::endl; + std::cout << "offset " << variable.m_Offsets.size() << std::endl; for (int i = 0; i < m_SizeMPI; ++i) { if (i == m_RankMPI) diff --git a/include/functions/adiosTemplates.h b/include/functions/adiosTemplates.h index a1a7a2441231f0beca474d4d0f39bfa213beb44c..5640c538758c70c62511f68443153dafb34f80be 100644 --- a/include/functions/adiosTemplates.h +++ b/include/functions/adiosTemplates.h @@ -271,15 +271,15 @@ void MemcpyToBuffer(std::vector<char> &raw, std::size_t &position, * @param elements */ template <class T> -void CopyToBuffer(std::vector<char> &buffer, const T *source, - const std::size_t elements = 1) noexcept +void InsertToBuffer(std::vector<char> &buffer, const T *source, + const std::size_t elements = 1) noexcept { const char *src = reinterpret_cast<const char *>(source); buffer.insert(buffer.end(), src, src + elements * sizeof(T)); } /** - * Overloaded version to copies data to a specific location in the buffer, + * Copies data to a specific location in the buffer, * doesn't update vec.size() * @param raw * @param position @@ -287,8 +287,9 @@ void CopyToBuffer(std::vector<char> &buffer, const T *source, * @param elements */ template <class T> -void CopyToBuffer(std::vector<char> &buffer, const std::size_t position, - const T *source, const std::size_t elements = 1) noexcept +void CopyToBufferPosition(std::vector<char> &buffer, const std::size_t position, + const T *source, + const std::size_t elements = 1) noexcept { const char *src = reinterpret_cast<const char *>(source); std::copy(src, src + elements * sizeof(T), buffer.begin() + position); diff --git a/include/transport/wan/MdtmMan.h b/include/transport/wan/MdtmMan.h index 7ddd162acc11beb73abedab6f43aad5c9dd0b7ae..78f0f92b8aadbc28d4c3858286d4392979151ee0 100644 --- a/include/transport/wan/MdtmMan.h +++ b/include/transport/wan/MdtmMan.h @@ -14,7 +14,7 @@ #include "core/Transport.h" #include "external/json.hpp" -#include "DataMan.h" //here comes your DataMan header +#include "utilities/realtime/dataman/DataManBase.h" namespace adios { @@ -43,7 +43,7 @@ public: const std::vector<int> priorities, MPI_Comm mpiComm, const bool debugMode); - ~MdtmMan(); + virtual ~MdtmMan() = default; void Open(const std::string name, const std::string accessMode); diff --git a/include/utilities/format/bp1/BP1Writer.h b/include/utilities/format/bp1/BP1Writer.h index 3dc4db2b15e6145ef811031a5e4bfbd088c1b1ec..e293077713319b5d182aec28afd3a0a18c9933a7 100644 --- a/include/utilities/format/bp1/BP1Writer.h +++ b/include/utilities/format/bp1/BP1Writer.h @@ -15,10 +15,12 @@ #include <algorithm> //std::count, std::copy, std::for_each #include <cmath> //std::ceil #include <cstring> //std::memcpy +/// \endcond +#include "ADIOSMacros.h" +#include "ADIOSTypes.h" #include "utilities/format/bp1/BP1Base.h" #include "utilities/format/bp1/BP1Structs.h" -/// \endcond #include "capsule/heap/STLVector.h" #include "core/Variable.h" @@ -78,44 +80,11 @@ public: * @return variable index size */ template <class T> - size_t GetVariableIndexSize(const Variable<T> &variable) const noexcept - { - // size_t indexSize = varEntryLength + memberID + lengthGroupName + - // groupName + lengthVariableName + lengthOfPath + path + datatype - size_t indexSize = 23; // without characteristics - indexSize += variable.m_Name.size(); - - // characteristics 3 and 4, check variable number of dimensions - const std::size_t dimensions = - variable.DimensionsSize(); // commas in CSV + 1 - indexSize += 28 * dimensions; // 28 bytes per dimension - indexSize += 1; // id - - // characteristics, offset + payload offset in data - indexSize += 2 * (1 + 8); - // characteristic 0, if scalar add value, for now only allowing string - if (dimensions == 1) - { - indexSize += sizeof(T); - indexSize += 1; // id - // must have an if here - indexSize += 2 + variable.m_Name.size(); - indexSize += 1; // id - } - - // characteristic statistics - if (m_Verbosity == 0) // default, only min and max - { - indexSize += 2 * (sizeof(T) + 1); - indexSize += 1 + 1; // id - } - - return indexSize + 12; /// extra 12 bytes in case of attributes - // need to add transform characteristics - } + std::size_t GetVariableIndexSize(const Variable<T> &variable) const + noexcept; /** - * Version for primitive types (except std::complex<T>) + * Write metadata for a given variable * @param variable * @param heap * @param metadataSet @@ -123,26 +92,7 @@ public: template <class T> void WriteVariableMetadata(const Variable<T> &variable, capsule::STLVector &heap, - BP1MetadataSet &metadataSet) const noexcept - { - Stats<T> stats = GetStats(variable); - WriteVariableMetadataCommon(variable, stats, heap, metadataSet); - } - - /** - * Overloaded version for std::complex<T> variables - * @param variable - * @param heap - * @param metadataSet - */ - template <class T> - void WriteVariableMetadata(const Variable<std::complex<T>> &variable, - capsule::STLVector &heap, - BP1MetadataSet &metadataSet) const noexcept - { - Stats<T> stats = GetStats(variable); - WriteVariableMetadataCommon(variable, stats, heap, metadataSet); - } + BP1MetadataSet &metadataSet) const noexcept; /** * Expensive part this is only for heap buffers need to adapt to vector of @@ -153,13 +103,13 @@ public: template <class T> void WriteVariablePayload(const Variable<T> &variable, capsule::STLVector &heap, - const unsigned int nthreads = 1) const noexcept - { - // EXPENSIVE part, might want to use threads if large, serial for now - CopyToBuffer(heap.m_Data, variable.m_AppValues, variable.TotalSize()); - heap.m_DataAbsolutePosition += variable.PayLoadSize(); - } + const unsigned int nthreads = 1) const noexcept; + /** + * Flattens data + * @param metadataSet + * @param buffer + */ void Advance(BP1MetadataSet &metadataSet, capsule::STLVector &buffer); /** @@ -190,173 +140,23 @@ public: noexcept; private: - template <class T, class U> - void WriteVariableMetadataCommon(const Variable<T> &variable, - Stats<U> &stats, capsule::STLVector &heap, - BP1MetadataSet &metadataSet) const noexcept - { - stats.TimeIndex = metadataSet.TimeStep; - - // Get new Index or point to existing index - bool isNew = true; // flag to check if variable is new - BP1Index &varIndex = - GetBP1Index(variable.m_Name, metadataSet.VarsIndices, isNew); - stats.MemberID = varIndex.MemberID; - - // write metadata header in data and extract offsets - stats.Offset = heap.m_DataAbsolutePosition; - WriteVariableMetadataInData(variable, stats, heap); - stats.PayloadOffset = heap.m_DataAbsolutePosition; - - // write to metadata index - WriteVariableMetadataInIndex(variable, stats, isNew, varIndex); - - ++metadataSet.DataPGVarsCount; - } - - template <class T, class U> - void WriteVariableMetadataInData(const Variable<T> &variable, - const Stats<U> &stats, - capsule::STLVector &heap) const noexcept - { - auto &buffer = heap.m_Data; - - const std::size_t varLengthPosition = - buffer.size(); // capture initial position for variable length - buffer.insert(buffer.end(), 8, 0); // skip var length (8) - CopyToBuffer(buffer, &stats.MemberID); // memberID - WriteNameRecord(variable.m_Name, buffer); // variable name - buffer.insert(buffer.end(), 2, 0); // skip path - const std::uint8_t dataType = GetDataType<T>(); // dataType - CopyToBuffer(buffer, &dataType); - constexpr char no = 'n'; // isDimension - CopyToBuffer(buffer, &no); - - // write variable dimensions - const std::uint8_t dimensions = variable.m_LocalDimensions.size(); - CopyToBuffer(buffer, &dimensions); // count - std::uint16_t dimensionsLength = - 27 * - dimensions; // 27 is from 9 bytes for each: var y/n + local, var - // y/n + global dimension, var y/n + global offset, - // changed for characteristic - CopyToBuffer(buffer, &dimensionsLength); // length - WriteDimensionsRecord(buffer, variable.m_LocalDimensions, - variable.m_GlobalDimensions, variable.m_Offsets, - 18, true); - - // CHARACTERISTICS - WriteVariableCharacteristics(variable, stats, buffer, true); - - // Back to varLength including payload size - const std::uint64_t varLength = buffer.size() - varLengthPosition + - variable.PayLoadSize() - - 8; // remove its own size - CopyToBuffer(buffer, varLengthPosition, &varLength); // length - - heap.m_DataAbsolutePosition += - buffer.size() - varLengthPosition; // update absolute position to be - // used as payload position - } - - template <class T, class U> - void WriteVariableMetadataInIndex(const Variable<T> &variable, - const Stats<U> &stats, const bool isNew, - BP1Index &index) const noexcept - { - auto &buffer = index.Buffer; - - if (isNew == true) // write variable header (might be shared with - // attributes index) - { - buffer.insert(buffer.end(), 4, 0); // skip var length (4) - CopyToBuffer(buffer, &stats.MemberID); - buffer.insert(buffer.end(), 2, 0); // skip group name - WriteNameRecord(variable.m_Name, buffer); - buffer.insert(buffer.end(), 2, 0); // skip path - - const std::uint8_t dataType = GetDataType<T>(); - CopyToBuffer(buffer, &dataType); - - // Characteristics Sets Count in Metadata - index.Count = 1; - CopyToBuffer(buffer, &index.Count); - } - else // update characteristics sets count - { - const std::size_t characteristicsSetsCountPosition = - 15 + variable.m_Name.size(); - ++index.Count; - CopyToBuffer(buffer, characteristicsSetsCountPosition, - &index.Count); // test - } - - WriteVariableCharacteristics(variable, stats, buffer); - } - - template <class T, class U> - void WriteVariableCharacteristics(const Variable<T> &variable, - const Stats<U> &stats, - std::vector<char> &buffer, - const bool addLength = false) const - noexcept - { - const std::size_t characteristicsCountPosition = - buffer.size(); // very important to track as writer is going back to - // this position - buffer.insert(buffer.end(), 5, - 0); // skip characteristics count(1) + length (4) - std::uint8_t characteristicsCounter = 0; - - // DIMENSIONS - std::uint8_t characteristicID = characteristic_dimensions; - CopyToBuffer(buffer, &characteristicID); - const std::uint8_t dimensions = variable.m_LocalDimensions.size(); - - if (addLength == true) - { - const std::int16_t lengthOfDimensionsCharacteristic = - 24 * dimensions + - 3; // 24 = 3 local, global, global offset x 8 bytes/each - CopyToBuffer(buffer, &lengthOfDimensionsCharacteristic); - } - - CopyToBuffer(buffer, &dimensions); // count - const std::uint16_t dimensionsLength = 24 * dimensions; - CopyToBuffer(buffer, &dimensionsLength); // length - WriteDimensionsRecord(buffer, variable.m_LocalDimensions, - variable.m_GlobalDimensions, variable.m_Offsets, - 16, addLength); - ++characteristicsCounter; - - // VALUE for SCALAR or STAT min, max for ARRAY - WriteBoundsRecord(variable.m_IsScalar, stats, buffer, - characteristicsCounter, addLength); - // TIME INDEX - WriteCharacteristicRecord(characteristic_time_index, stats.TimeIndex, - buffer, characteristicsCounter, addLength); + template <class T> + void WriteVariableMetadataInData( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, + capsule::STLVector &heap) const noexcept; - if (addLength == false) // only in metadata offset and payload offset - { - WriteCharacteristicRecord(characteristic_offset, stats.Offset, - buffer, characteristicsCounter); - WriteCharacteristicRecord(characteristic_payload_offset, - stats.PayloadOffset, buffer, - characteristicsCounter); - } - // END OF CHARACTERISTICS + template <class T> + void WriteVariableMetadataInIndex( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, const bool isNew, + BP1Index &index) const noexcept; - // Back to characteristics count and length - CopyToBuffer(buffer, characteristicsCountPosition, - &characteristicsCounter); // count (1) - const std::uint32_t characteristicsLength = - buffer.size() - characteristicsCountPosition - 4 - - 1; // remove its own length (4 bytes) + characteristic counter ( 1 - // byte - // ) - CopyToBuffer(buffer, characteristicsCountPosition + 1, - &characteristicsLength); // length - } + template <class T> + void WriteVariableCharacteristics( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, + std::vector<char> &buffer, const bool addLength = false) const noexcept; /** * Writes from &buffer[position]: [2 @@ -389,80 +189,19 @@ private: const bool addType = false) const noexcept; /** - * GetStats for primitive types except std::complex<T> types + * Get variable statistics * @param variable * @return stats */ template <class T> - Stats<T> GetStats(const Variable<T> &variable) const noexcept - { - Stats<T> stats; - const std::size_t valuesSize = variable.TotalSize(); - - if (m_Verbosity == 0) - { - if (valuesSize >= - 10000000) // ten million? this needs actual results - // //here we can make decisions for threads - // based on valuesSize - GetMinMax(variable.m_AppValues, valuesSize, stats.Min, - stats.Max, - m_Threads); // here we can add cores from constructor - else - GetMinMax(variable.m_AppValues, valuesSize, stats.Min, - stats.Max); - } - return stats; - } - - /** - * GetStats for std::complex<T> types - * @param variable - * @return stats - */ - template <class T> - Stats<T> GetStats(const Variable<std::complex<T>> &variable) const noexcept - { - Stats<T> stats; - const std::size_t valuesSize = variable.TotalSize(); - - if (m_Verbosity == 0) - { - if (valuesSize >= - 10000000) // ten million? this needs actual results - // //here we can make decisions for threads - // based on valuesSize - GetMinMax(variable.m_AppValues, valuesSize, stats.Min, - stats.Max, m_Threads); - else - GetMinMax(variable.m_AppValues, valuesSize, stats.Min, - stats.Max); - } - return stats; - } + Stats<typename TypeInfo<T>::ValueType> + GetStats(const Variable<T> &variable) const noexcept; template <class T> void WriteBoundsRecord(const bool isScalar, const Stats<T> &stats, std::vector<char> &buffer, std::uint8_t &characteristicsCounter, - const bool addLength) const noexcept - { - if (isScalar == true) - { - WriteCharacteristicRecord( - characteristic_value, stats.Min, buffer, characteristicsCounter, - addLength); // stats.min = stats.max = value - return; - } - - if (m_Verbosity == 0) // default verbose - { - WriteCharacteristicRecord(characteristic_min, stats.Min, buffer, - characteristicsCounter, addLength); - WriteCharacteristicRecord(characteristic_max, stats.Max, buffer, - characteristicsCounter, addLength); - } - } + const bool addLength) const noexcept; /** * Write a characteristic value record to buffer @@ -477,25 +216,11 @@ private: void WriteCharacteristicRecord(const std::uint8_t characteristicID, const T &value, std::vector<char> &buffer, std::uint8_t &characteristicsCounter, - const bool addLength = false) const noexcept - { - const std::uint8_t id = characteristicID; - CopyToBuffer(buffer, &id); - - if (addLength == true) - { - const std::uint16_t lengthOfCharacteristic = sizeof(T); // id - CopyToBuffer(buffer, &lengthOfCharacteristic); - } - - CopyToBuffer(buffer, &value); - ++characteristicsCounter; - } + const bool addLength = false) const noexcept; /** * Returns corresponding index of type BP1Index, if doesn't exists creates a - * new one. - * Used for variables and attributes + * new one. Used for variables and attributes * @param name variable or attribute name to look for index * @param indices look up hash table of indices * @param isNew true: index is newly created, false: index already exists in @@ -521,11 +246,21 @@ private: * @param buffer */ void FlattenMetadata(BP1MetadataSet &metadataSet, - capsule::STLVector &buffer) const - noexcept; ///< sets the metadata buffer in capsule with indices and - /// minifooter + capsule::STLVector &buffer) const noexcept; }; +#define declare_template_instantiation(T) \ + extern template void BP1Writer::WriteVariablePayload( \ + const Variable<T> &variable, capsule::STLVector &heap, \ + const unsigned int nthreads) const noexcept; \ + \ + extern template void BP1Writer::WriteVariableMetadata( \ + const Variable<T> &variable, capsule::STLVector &heap, \ + BP1MetadataSet &metadataSet) const noexcept; + +ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + } // end namespace format } // end namespace adios diff --git a/include/utilities/realtime/dataman/DataMan.h b/include/utilities/realtime/dataman/DataMan.h new file mode 100644 index 0000000000000000000000000000000000000000..59640e933fd9e1a5dc12800a2b3e924ff42bf92c --- /dev/null +++ b/include/utilities/realtime/dataman/DataMan.h @@ -0,0 +1,54 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * DataMan.h + * + * Created on: Apr 12, 2017 + * Author: Jason Wang + */ + +#ifndef DATAMANAGER_H_ +#define DATAMANAGER_H_ + +#include "utilities/realtime/dataman/DataManBase.h" + +namespace adios +{ +namespace realtime +{ + +class DataMan : public DataManBase +{ +public: + DataMan() = default; + virtual ~DataMan() = default; + virtual int init(json p_jmsg); + virtual int put(const void *p_data, json p_jmsg); + virtual int get(void *p_data, json &p_jmsg); + void flush(); + void add_stream(json p_jmsg); + int put(const void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_putshape, + std::vector<size_t> p_varshape, std::vector<size_t> p_offset, + size_t p_timestep, int p_tolerance = 0, int p_priority = 100); + void add_file(std::string p_method); + std::string name() { return "DataManager"; } + std::string type() { return "Manager"; } + virtual void transform(const void *p_in, void *p_out, json &p_jmsg){}; + +private: + std::string m_local_ip = ""; + std::string m_remote_ip = ""; + int m_local_port = 0; + int m_remote_port = 0; + int m_num_channels = 0; + std::vector<int> m_tolerance; + std::vector<int> m_priority; +}; + +// end namespace realtime +} +// end namespace adios +} +#endif diff --git a/include/utilities/realtime/dataman/DataManBase.h b/include/utilities/realtime/dataman/DataManBase.h new file mode 100644 index 0000000000000000000000000000000000000000..9d14457427a4feeaeff65222c1d6a42fef352a12 --- /dev/null +++ b/include/utilities/realtime/dataman/DataManBase.h @@ -0,0 +1,283 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * DataManBase.h + * + * Created on: Apr 12, 2017 + * Author: Jason Wang + */ + +#ifndef DATAMAN_H_ +#define DATAMAN_H_ + +#include <cstdint> + +#include <dlfcn.h> +#include <unistd.h> + +#include <chrono> +#include <complex> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <vector> + +#include "external/json.hpp" + +namespace adios +{ +namespace realtime +{ + +class DataManBase +{ +public: + using json = nlohmann::json; + DataManBase(); + virtual ~DataManBase() = default; + int put(const void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_putshape, + std::vector<size_t> p_varshape, std::vector<size_t> p_offset, + size_t p_timestep, int p_tolerance = 0, int p_priority = 100); + + virtual int put_begin(const void *p_data, json &p_jmsg); + + virtual int put_end(const void *p_data, json &p_jmsg); + + virtual int put(const void *p_data, json p_jmsg) = 0; + + int get(void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_getshape, + std::vector<size_t> p_varshape, std::vector<size_t> p_offset, + size_t p_timestep); + + int get(void *p_data, std::string p_doid, std::string p_var, + std::string &p_dtype, std::vector<size_t> &p_varshape, + size_t &p_timestep); + + virtual int get(void *p_data, json &p_jmsg) = 0; + virtual int init(json p_jmsg) = 0; + virtual void flush() = 0; + virtual std::string name() = 0; + virtual std::string type() = 0; + void reg_callback(std::function<void(const void *, std::string, std::string, + std::string, std::vector<size_t>)> + cb); + + void dump(const void *p_data, json p_jmsg, std::ostream &out = std::cout); + + void add_next(std::string p_name, std::shared_ptr<DataManBase> p_next); + + void remove_next(std::string p_name); + + bool have_next(); + + void print_next(std::ostream &out = std::cout); + + virtual void transform(const void *p_in, void *p_out, json &p_jmsg) = 0; + +protected: + bool auto_transform(const void *p_in, void *p_out, json &p_jmsg); + + void add_man_to_path(std::string p_new, std::string p_path); + + virtual int flush_next(); + + virtual int put_next(const void *p_data, json p_jmsg); + + std::shared_ptr<DataManBase> get_man(std::string method); + + inline void logging(std::string p_msg, std::string p_man = "", + std::ostream &out = std::cout) + { + if (p_man == "") + p_man = name(); + out << "["; + out << p_man; + out << "]"; + out << " "; + out << p_msg; + out << std::endl; + } + + inline bool check_json(json p_jmsg, std::vector<std::string> p_strings, + std::string p_man = "") + { + if (p_man == "") + p_man = name(); + for (auto i : p_strings) + { + if (p_jmsg[i] == nullptr) + { + if (p_man != "") + { + logging("JSON key " + i + " not found!", p_man); + } + return false; + } + } + return true; + } + + inline size_t product(size_t *shape) + { + size_t s = 1; + if (shape) + { + for (size_t i = 1; i <= shape[0]; i++) + { + s *= shape[i]; + } + } + return s; + } + + inline size_t product(std::vector<size_t> shape, size_t size = 1) + { + return accumulate(shape.begin(), shape.end(), size, + std::multiplies<size_t>()); + } + + inline size_t dsize(std::string dtype) + { + if (dtype == "char") + return sizeof(char); + if (dtype == "short") + return sizeof(short); + if (dtype == "int") + return sizeof(int); + if (dtype == "long") + return sizeof(long); + if (dtype == "unsigned char") + return sizeof(unsigned char); + if (dtype == "unsigned short") + return sizeof(unsigned short); + if (dtype == "unsigned int") + return sizeof(unsigned int); + if (dtype == "unsigned long") + return sizeof(unsigned long); + if (dtype == "float") + return sizeof(float); + if (dtype == "double") + return sizeof(double); + if (dtype == "long double") + return sizeof(long double); + if (dtype == "std::complex<float>" or dtype == "complex<float>") + return sizeof(std::complex<float>); + if (dtype == "std::complex<double>") + return sizeof(std::complex<double>); + + if (dtype == "int8_t") + return sizeof(int8_t); + if (dtype == "uint8_t") + return sizeof(uint8_t); + if (dtype == "int16_t") + return sizeof(int16_t); + if (dtype == "uint16_t") + return sizeof(uint16_t); + if (dtype == "int32_t") + return sizeof(int32_t); + if (dtype == "uint32_t") + return sizeof(uint32_t); + if (dtype == "int64_t") + return sizeof(int64_t); + if (dtype == "uint64_t") + return sizeof(uint64_t); + return 0; + } + + inline json atoj(unsigned int *array) + { + json j; + if (array) + { + if (array[0] > 0) + { + j = {array[1]}; + for (unsigned int i = 2; i <= array[0]; i++) + { + j.insert(j.end(), array[i]); + } + } + } + return j; + } + + inline std::string rmquote(std::string in) + { + return in.substr(1, in.length() - 2); + } + + inline bool isin(std::string a, json j) + { + for (unsigned int i = 0; i < j.size(); i++) + { + if (j[i] == a) + return true; + } + return false; + } + + inline int closest(int v, json j, bool up) + { + int s = 100, k = 0, t; + for (unsigned int i = 0; i < j.size(); i++) + { + if (up) + t = j[i].get<int>() - v; + else + t = v - j[i].get<int>(); + if (t >= 0 && t < s) + { + s = t; + k = i; + } + } + return k; + } + + inline void check_shape(json &p_jmsg) + { + std::vector<size_t> varshape; + if (check_json(p_jmsg, {"varshape"})) + { + varshape = p_jmsg["varshape"].get<std::vector<size_t>>(); + } + else + { + return; + } + if (p_jmsg["putshape"] == nullptr) + { + p_jmsg["putshape"] = varshape; + } + if (p_jmsg["offset"] == nullptr) + { + p_jmsg["offset"] = std::vector<size_t>(varshape.size(), 0); + } + p_jmsg["putbytes"] = + product(p_jmsg["putshape"].get<std::vector<size_t>>(), + dsize(p_jmsg["dtype"].get<std::string>())); + p_jmsg["varbytes"] = + product(varshape, dsize(p_jmsg["dtype"].get<std::string>())); + } + + std::function<void(const void *, std::string, std::string, std::string, + std::vector<size_t>)> + m_callback; + std::map<std::string, std::shared_ptr<DataManBase>> m_next; + +private: + json m_profiling; + std::chrono::time_point<std::chrono::system_clock> m_start_time; + std::chrono::time_point<std::chrono::system_clock> m_step_time; + bool m_profiling_enabled = false; +}; + +// end namespace realtime +} +// end namespace adios +} +#endif diff --git a/source/ADIOS.cpp b/source/ADIOS.cpp index 5925f5e30013980c0048ba52eea0bdca05dca26c..30aac797cd4d6533626106baef0dcab3eeed529b 100644 --- a/source/ADIOS.cpp +++ b/source/ADIOS.cpp @@ -18,6 +18,7 @@ #include "ADIOS.h" #include "ADIOS.tcc" +#include "ADIOSMacros.h" #include "functions/adiosFunctions.h" @@ -396,4 +397,19 @@ void ADIOS::CheckMethod(std::map<std::string, Method>::const_iterator itMethod, } } +//------------------------------------------------------------------------------ + +// Explicitly instantiate the necessary template implementations +#define define_template_instantiation(T) \ + template Variable<T> &ADIOS::DefineVariable<T>( \ + const std::string &, const Dims, const Dims, const Dims); \ + \ + template Variable<T> &ADIOS::GetVariable<T>(const std::string &); + +ADIOS_FOREACH_TYPE_1ARG(define_template_instantiation) +template unsigned int ADIOS::GetVariableIndex<void>(const std::string &); +#undef define_template_instatiation + +//------------------------------------------------------------------------------ + } // end namespace adios diff --git a/source/ADIOS_inst.cpp b/source/ADIOS.tcc similarity index 77% rename from source/ADIOS_inst.cpp rename to source/ADIOS.tcc index 81b91e56c6acdffc0e83fd0be83843310db6ef60..44d95a9fd26d1edcb9e1061efeee21fa5ec594bf 100644 --- a/source/ADIOS_inst.cpp +++ b/source/ADIOS.tcc @@ -6,7 +6,10 @@ * This contains the template specializatios for the ADIOS class */ -#include "ADIOS.tcc" +#ifndef ADIOS_TCC_ +#define ADIOS_TCC_ + +#include "ADIOS.h" #include "ADIOSMacros.h" namespace adios @@ -114,8 +117,6 @@ ADIOS::GetVariableMap() return m_CLDouble; } -// ----------------------------------------------------------------------------- -// explicit template instantiations of DefineVariable: // ----------------------------------------------------------------------------- template <typename T> @@ -133,14 +134,6 @@ ADIOS::DefineVariable(const std::string &name, const Dims globalDimensions, return variableMap.at(size); } -#define define_template_instantiation(T) \ - template Variable<T> &ADIOS::DefineVariable<T>( \ - const std::string &, const Dims, const Dims, const Dims); -ADIOS_FOREACH_TYPE_1ARG(define_template_instantiation) -#undef define_template_instatiation - -// ----------------------------------------------------------------------------- -// template specializations of GetVariable: // ----------------------------------------------------------------------------- template <class T> @@ -160,11 +153,6 @@ Variable<T> &ADIOS::GetVariable(const std::string &name) return GetVariableMap<T>().at(GetVariableIndex<T>(name)); } -#define define_template_instatiation(T) \ - template unsigned int ADIOS::GetVariableIndex<T>(const std::string &); \ - template Variable<T> &ADIOS::GetVariable<T>(const std::string &); -ADIOS_FOREACH_TYPE_1ARG(define_template_instatiation) -template unsigned int ADIOS::GetVariableIndex<void>(const std::string &); -#undef define_template_instatiation - } // end namespace adios + +#endif // ADIOS_TCC_ diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 975ae6dcc50fada18d35a0b6fe442da05d078fc9..62a642e966648cd5d2d73c4473146429920fa58a 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -10,7 +10,7 @@ endif() foreach(adios2_target IN LISTS adios2_targets) add_library(${adios2_target} - ADIOS.cpp ADIOS_inst.cpp + ADIOS.cpp ADIOS.tcc #ADIOS_C.cpp capsule/heap/STLVector.cpp @@ -37,20 +37,28 @@ foreach(adios2_target IN LISTS adios2_targets) transport/file/FStream.cpp transport/file/FileDescriptor.cpp transport/file/FilePointer.cpp + + utilities/format/bp1/BP1Base.cpp + utilities/format/bp1/BP1Aggregator.cpp + utilities/format/bp1/BP1Writer.cpp + utilities/format/bp1/BP1Writer.tcc + + utilities/profiling/iochrono/Timer.cpp ) target_include_directories(${adios2_target} PUBLIC ${ADIOS_SOURCE_DIR}/include ) if(ADIOS_USE_DataMan) - find_package(DataMan REQUIRED) target_sources(${adios2_target} PRIVATE engine/dataman/DataManReader.cpp engine/dataman/DataManWriter.cpp transport/wan/MdtmMan.cpp + utilities/realtime/dataman/DataManBase.cpp + utilities/realtime/dataman/DataMan.cpp ) target_compile_definitions(${adios2_target} PRIVATE ADIOS_HAVE_DATAMAN) - target_link_libraries(${adios2_target} PRIVATE DataMan::DataMan) + target_link_libraries(${adios2_target} PRIVATE ${CMAKE_DL_LIBS}) endif() diff --git a/source/core/Method.cpp b/source/core/Method.cpp index 720382cc26074a531918f3c6d21c210ad56dae1f..0c91ed23a3d35da0b5b776954d07eccf84a2233a 100644 --- a/source/core/Method.cpp +++ b/source/core/Method.cpp @@ -29,6 +29,7 @@ bool Method::IsUserDefined() } void Method::SetEngine(const std::string type) { m_Type = type; } +void Method::SetIOMode(const IOMode mode) { m_IOMode = mode; }; void Method::AllowThreads(const unsigned int nThreads) { diff --git a/source/engine/adios1/ADIOS1Reader.cpp b/source/engine/adios1/ADIOS1Reader.cpp index 55a745a0e7370a437665321105cc3ecafd5e9f26..f938277af392b605f7fffa082d61e2f2a7cd7ee7 100644 --- a/source/engine/adios1/ADIOS1Reader.cpp +++ b/source/engine/adios1/ADIOS1Reader.cpp @@ -2,14 +2,14 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * BPFileReader.cpp + * ADIOS1Reader.cpp * * Created on: Feb 27, 2017 * Author: wfg */ +#include "engine/adios1/ADIOS1Reader.h" #include "core/Support.h" -#include "engine/bp/BPFileReader.h" #include "functions/adiosFunctions.h" // CSVToVector #include "transport/file/FStream.h" // uses C++ fstream #include "transport/file/FileDescriptor.h" // uses POSIX @@ -21,127 +21,128 @@ namespace adios ADIOS1Reader::ADIOS1Reader(ADIOS &adios, const std::string &name, const std::string accessMode, MPI_Comm mpiComm, const Method &method) -: Engine(adios, "BPFileReader", name, accessMode, mpiComm, method, - " BPFileReader constructor (or call to ADIOS Open).\n") +: Engine(adios, "ADIOS1Reader", name, accessMode, mpiComm, method, + " ADIOS1Reader constructor (or call to ADIOS Open).\n") { Init(); + adios_read_init_method(read_method, mpiComm, ""); } -BPFileReader::~BPFileReader() {} +ADIOS1Reader::~ADIOS1Reader() {} Variable<void> * -BPFileReader::InquireVariable(const std::string &variableName, +ADIOS1Reader::InquireVariable(const std::string &variableName, const bool readIn) // not yet implemented { return nullptr; } Variable<char> * -BPFileReader::InquireVariableChar(const std::string &variableName, +ADIOS1Reader::InquireVariableChar(const std::string &variableName, const bool readIn) { return InquireVariableCommon<char>(variableName, readIn); } Variable<unsigned char> * -BPFileReader::InquireVariableUChar(const std::string &variableName, +ADIOS1Reader::InquireVariableUChar(const std::string &variableName, const bool readIn) { return InquireVariableCommon<unsigned char>(variableName, readIn); } Variable<short> * -BPFileReader::InquireVariableShort(const std::string &variableName, +ADIOS1Reader::InquireVariableShort(const std::string &variableName, const bool readIn) { return InquireVariableCommon<short>(variableName, readIn); } Variable<unsigned short> * -BPFileReader::InquireVariableUShort(const std::string &variableName, +ADIOS1Reader::InquireVariableUShort(const std::string &variableName, const bool readIn) { return InquireVariableCommon<unsigned short>(variableName, readIn); } -Variable<int> *BPFileReader::InquireVariableInt(const std::string &variableName, +Variable<int> *ADIOS1Reader::InquireVariableInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<int>(variableName, readIn); } Variable<unsigned int> * -BPFileReader::InquireVariableUInt(const std::string &variableName, +ADIOS1Reader::InquireVariableUInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<unsigned int>(variableName, readIn); } Variable<long int> * -BPFileReader::InquireVariableLInt(const std::string &variableName, +ADIOS1Reader::InquireVariableLInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<long int>(variableName, readIn); } Variable<unsigned long int> * -BPFileReader::InquireVariableULInt(const std::string &variableName, +ADIOS1Reader::InquireVariableULInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<unsigned long int>(variableName, readIn); } Variable<long long int> * -BPFileReader::InquireVariableLLInt(const std::string &variableName, +ADIOS1Reader::InquireVariableLLInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<long long int>(variableName, readIn); } Variable<unsigned long long int> * -BPFileReader::InquireVariableULLInt(const std::string &variableName, +ADIOS1Reader::InquireVariableULLInt(const std::string &variableName, const bool readIn) { return InquireVariableCommon<unsigned long long int>(variableName, readIn); } Variable<float> * -BPFileReader::InquireVariableFloat(const std::string &variableName, +ADIOS1Reader::InquireVariableFloat(const std::string &variableName, const bool readIn) { return InquireVariableCommon<float>(variableName, readIn); } Variable<double> * -BPFileReader::InquireVariableDouble(const std::string &variableName, +ADIOS1Reader::InquireVariableDouble(const std::string &variableName, const bool readIn) { return InquireVariableCommon<double>(variableName, readIn); } Variable<long double> * -BPFileReader::InquireVariableLDouble(const std::string &variableName, +ADIOS1Reader::InquireVariableLDouble(const std::string &variableName, const bool readIn) { return InquireVariableCommon<long double>(variableName, readIn); } Variable<std::complex<float>> * -BPFileReader::InquireVariableCFloat(const std::string &variableName, +ADIOS1Reader::InquireVariableCFloat(const std::string &variableName, const bool readIn) { return InquireVariableCommon<std::complex<float>>(variableName, readIn); } Variable<std::complex<double>> * -BPFileReader::InquireVariableCDouble(const std::string &variableName, +ADIOS1Reader::InquireVariableCDouble(const std::string &variableName, const bool readIn) { return InquireVariableCommon<std::complex<double>>(variableName, readIn); } Variable<std::complex<long double>> * -BPFileReader::InquireVariableCLDouble(const std::string &variableName, +ADIOS1Reader::InquireVariableCLDouble(const std::string &variableName, const bool readIn) { return InquireVariableCommon<std::complex<long double>>(variableName, @@ -149,31 +150,34 @@ BPFileReader::InquireVariableCLDouble(const std::string &variableName, } VariableCompound * -BPFileReader::InquireVariableCompound(const std::string &variableName, +ADIOS1Reader::InquireVariableCompound(const std::string &variableName, const bool readIn) { return nullptr; } -void BPFileReader::Close(const int transportIndex) {} +void ADIOS1Reader::Close(const int transportIndex) {} // PRIVATE -void BPFileReader::Init() +void ADIOS1Reader::Init() { if (m_DebugMode == true) { if (m_AccessMode != "r" && m_AccessMode != "read") throw std::invalid_argument( - "ERROR: BPFileReader doesn't support access mode " + + "ERROR: ADIOS1Reader doesn't support access mode " + m_AccessMode + - ", in call to ADIOS Open or BPFileReader constructor\n"); + ", in call to ADIOS Open or ADIOS1Reader constructor\n"); } - + InitParameters(); InitTransports(); } -void BPFileReader::InitTransports() // maybe move this? +void ADIOS1Reader::InitParameters() {} + +void ADIOS1Reader::InitTransports() { + if (m_DebugMode == true) { if (TransportNamesUniqueness() == false) @@ -188,43 +192,10 @@ void BPFileReader::InitTransports() // maybe move this? for (const auto ¶meters : m_Method.m_TransportParameters) { auto itTransport = parameters.find("transport"); - if (itTransport->second == "file" || itTransport->second == "File") + if (itTransport->second == "file" || itTransport->second == "File" || + itTransport->second == "bp" || itTransport->second == "BP") { - auto itLibrary = parameters.find("library"); - if (itLibrary == parameters.end() || - itLibrary->second == "POSIX") // use default POSIX - { - auto file = std::make_shared<transport::FileDescriptor>( - m_MPIComm, m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "FILE*" || - itLibrary->second == "stdio.h") - { - auto file = std::make_shared<transport::FilePointer>( - m_MPIComm, m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "fstream" || - itLibrary->second == "std::fstream") - { - auto file = std::make_shared<transport::FStream>(m_MPIComm, - m_DebugMode); - // m_BP1Reader.OpenRankFiles( m_Name, m_AccessMode, *file ); - m_Transports.push_back(std::move(file)); - } - else if (itLibrary->second == "MPI-IO") - { - } - else - { - if (m_DebugMode == true) - throw std::invalid_argument( - "ERROR: file transport library " + itLibrary->second + - " not supported, in " + m_Name + m_EndMessage); - } + read_method = ADIOS_READ_METHOD_BP; } else { diff --git a/source/engine/dataman/DataManReader.cpp b/source/engine/dataman/DataManReader.cpp index f90c446d885f3eb23a3e36f8c7d590c343c2b4ae..4ad22bcb8f7d3f47f68711499cbb2ffdfc37160d 100644 --- a/source/engine/dataman/DataManReader.cpp +++ b/source/engine/dataman/DataManReader.cpp @@ -11,6 +11,7 @@ #include "engine/dataman/DataManReader.h" #include "core/Support.h" +#include "external/json.hpp" #include "functions/adiosFunctions.h" //CSVToVector // supported transports @@ -19,23 +20,19 @@ #include "transport/file/FilePointer.h" // uses C FILE* #include "transport/wan/MdtmMan.h" //uses Mdtm library -#include "DataMan.h" //here comes your DataMan header from external dataman library - namespace adios { -DataManReader::DataManReader(ADIOS &adios, const std::string name, +DataManReader::DataManReader(ADIOS &adios, const std::string &name, const std::string accessMode, MPI_Comm mpiComm, const Method &method) : Engine(adios, "DataManReader", name, accessMode, mpiComm, method, - " DataManReader constructor (or call to ADIOS Open).\n") -// m_Buffer(accessMode, m_RankMPI, m_DebugMode) + " DataManReader constructor (or call to ADIOS Open).\n"), + m_Buffer(accessMode, m_RankMPI, m_DebugMode) { Init(); } -DataManReader::~DataManReader() {} - void DataManReader::SetCallBack( std::function<void(const void *, std::string, std::string, std::string, Dims)> @@ -46,111 +43,114 @@ void DataManReader::SetCallBack( } Variable<void> * -DataManReader::InquireVariable(const std::string name, +DataManReader::InquireVariable(const std::string &name, const bool readIn) // not yet implemented { return nullptr; } -Variable<char> *DataManReader::InquireVariableChar(const std::string name, +Variable<char> *DataManReader::InquireVariableChar(const std::string &name, const bool readIn) { return InquireVariableCommon<char>(name, readIn); } Variable<unsigned char> * -DataManReader::InquireVariableUChar(const std::string name, const bool readIn) +DataManReader::InquireVariableUChar(const std::string &name, const bool readIn) { return InquireVariableCommon<unsigned char>(name, readIn); } -Variable<short> *DataManReader::InquireVariableShort(const std::string name, +Variable<short> *DataManReader::InquireVariableShort(const std::string &name, const bool readIn) { return InquireVariableCommon<short>(name, readIn); } Variable<unsigned short> * -DataManReader::InquireVariableUShort(const std::string name, const bool readIn) +DataManReader::InquireVariableUShort(const std::string &name, const bool readIn) { return InquireVariableCommon<unsigned short>(name, readIn); } -Variable<int> *DataManReader::InquireVariableInt(const std::string name, +Variable<int> *DataManReader::InquireVariableInt(const std::string &name, const bool readIn) { return InquireVariableCommon<int>(name, readIn); } Variable<unsigned int> * -DataManReader::InquireVariableUInt(const std::string name, const bool readIn) +DataManReader::InquireVariableUInt(const std::string &name, const bool readIn) { return InquireVariableCommon<unsigned int>(name, readIn); } -Variable<long int> *DataManReader::InquireVariableLInt(const std::string name, +Variable<long int> *DataManReader::InquireVariableLInt(const std::string &name, const bool readIn) { return InquireVariableCommon<long int>(name, readIn); } Variable<unsigned long int> * -DataManReader::InquireVariableULInt(const std::string name, const bool readIn) +DataManReader::InquireVariableULInt(const std::string &name, const bool readIn) { return InquireVariableCommon<unsigned long int>(name, readIn); } Variable<long long int> * -DataManReader::InquireVariableLLInt(const std::string name, const bool readIn) +DataManReader::InquireVariableLLInt(const std::string &name, const bool readIn) { return InquireVariableCommon<long long int>(name, readIn); } Variable<unsigned long long int> * -DataManReader::InquireVariableULLInt(const std::string name, const bool readIn) +DataManReader::InquireVariableULLInt(const std::string &name, const bool readIn) { return InquireVariableCommon<unsigned long long int>(name, readIn); } -Variable<float> *DataManReader::InquireVariableFloat(const std::string name, +Variable<float> *DataManReader::InquireVariableFloat(const std::string &name, const bool readIn) { return InquireVariableCommon<float>(name, readIn); } -Variable<double> *DataManReader::InquireVariableDouble(const std::string name, +Variable<double> *DataManReader::InquireVariableDouble(const std::string &name, const bool readIn) { return InquireVariableCommon<double>(name, readIn); } Variable<long double> * -DataManReader::InquireVariableLDouble(const std::string name, const bool readIn) +DataManReader::InquireVariableLDouble(const std::string &name, + const bool readIn) { return InquireVariableCommon<long double>(name, readIn); } Variable<std::complex<float>> * -DataManReader::InquireVariableCFloat(const std::string name, const bool readIn) +DataManReader::InquireVariableCFloat(const std::string &name, const bool readIn) { return InquireVariableCommon<std::complex<float>>(name, readIn); } Variable<std::complex<double>> * -DataManReader::InquireVariableCDouble(const std::string name, const bool readIn) +DataManReader::InquireVariableCDouble(const std::string &name, + const bool readIn) { return InquireVariableCommon<std::complex<double>>(name, readIn); } Variable<std::complex<long double>> * -DataManReader::InquireVariableCLDouble(const std::string name, +DataManReader::InquireVariableCLDouble(const std::string &name, const bool readIn) { return InquireVariableCommon<std::complex<long double>>(name, readIn); } -VariableCompound *DataManReader::InquireVariableCompound(const std::string name, - const bool readIn) +VariableCompound * +DataManReader::InquireVariableCompound(const std::string &name, + const bool readIn) { return nullptr; } @@ -260,9 +260,10 @@ void DataManReader::InitTransports() // maybe move this? const std::vector<int> priorities = CSVToVectorInt(GetMdtmParameter("priorities", parameters)); - m_Transports.push_back(std::make_shared<transport::MdtmMan>( - localIP, remoteIP, m_AccessMode, prefix, numberOfPipes, - tolerances, priorities, m_MPIComm, m_DebugMode)); + // m_Transports.push_back(std::make_shared<transport::MdtmMan>( + // localIP, remoteIP, m_AccessMode, prefix, + // numberOfPipes, + // tolerances, priorities, m_MPIComm, m_DebugMode)); } else if (itTransport->second == "Zmq") { diff --git a/source/engine/dataman/DataManWriter.cpp b/source/engine/dataman/DataManWriter.cpp index de1cf8455a4cc0d60ecfb49e19d8a0c7193ce64b..7e438b535152f9acbbe80d2b037f98780772bf3a 100644 --- a/source/engine/dataman/DataManWriter.cpp +++ b/source/engine/dataman/DataManWriter.cpp @@ -32,8 +32,6 @@ DataManWriter::DataManWriter(ADIOS &adios, const std::string name, Init(); } -DataManWriter::~DataManWriter() {} - void DataManWriter::SetCallBack( std::function<void(const void *, std::string, std::string, std::string, Dims)> @@ -353,9 +351,10 @@ void DataManWriter::InitTransports() // maybe move this? const std::vector<int> priorities = CSVToVectorInt(GetMdtmParameter("priorities", parameters)); - m_Transports.push_back(std::make_shared<transport::MdtmMan>( - localIP, remoteIP, m_AccessMode, prefix, numberOfPipes, - tolerances, priorities, m_MPIComm, m_DebugMode)); + // m_Transports.push_back(std::make_shared<transport::MdtmMan>( + // localIP, remoteIP, m_AccessMode, prefix, + // numberOfPipes, + // tolerances, priorities, m_MPIComm, m_DebugMode)); } else if (itTransport->second == "Zmq") { diff --git a/source/transport/wan/MdtmMan.cpp b/source/transport/wan/MdtmMan.cpp index cdece2ecbfa5270b2e36eedb07af430319056cb1..c3fbdafd414ce82ceba78bfb8dbd0a7e950ce28b 100644 --- a/source/transport/wan/MdtmMan.cpp +++ b/source/transport/wan/MdtmMan.cpp @@ -27,8 +27,6 @@ MdtmMan::MdtmMan(const std::string localIP, const std::string remoteIP, { } -MdtmMan::~MdtmMan() {} - void MdtmMan::Open(const std::string name, const std::string accessMode) {} void MdtmMan::SetBuffer(char *buffer, std::size_t size) {} diff --git a/source/utilities/format/bp1/BP1Aggregator.cpp b/source/utilities/format/bp1/BP1Aggregator.cpp index b4468c03647989a1ce63c443b4493ede3771227a..1ad2d00e70e127253c0c810809fec21cf94d4a38 100644 --- a/source/utilities/format/bp1/BP1Aggregator.cpp +++ b/source/utilities/format/bp1/BP1Aggregator.cpp @@ -43,8 +43,10 @@ void BP1Aggregator::WriteProfilingLog(const std::string fileName, // first receive sizes for (unsigned int i = 1; i < sizeMPI; ++i) + { MPI_Irecv(&rankLogsSizes[i - 1], 1, MPI_INT, i, 0, m_MPIComm, &requests[i]); + } for (unsigned int i = 1; i < sizeMPI; ++i) { @@ -62,23 +64,37 @@ void BP1Aggregator::WriteProfilingLog(const std::string fileName, // receive rankLog from other ranks for (unsigned int i = 1; i < sizeMPI; ++i) + { MPI_Irecv(rankLogs[i - 1].data(), rankLogsSizes[i - 1], MPI_CHAR, i, 1, m_MPIComm, &requests[i]); + } for (unsigned int i = 1; i < sizeMPI; ++i) + { MPI_Wait(&requests[i], &statuses[i]); + } // write file - std::string logFile("log = { \n"); + std::string logFile("{\n"); logFile += rankLog + "\n"; for (unsigned int i = 1; i < sizeMPI; ++i) { - const std::string rankLogStr(rankLogs[i - 1].data(), - rankLogs[i - 1].size()); - logFile += rankLogStr + "\n"; + if (i == sizeMPI - 1) // last one, eliminate trailing comma + { + const std::string rankLogStr(rankLogs[i - 1].data(), + rankLogs[i - 1].size() - 1); + logFile += rankLogStr + "\n"; + } + else + { + const std::string rankLogStr(rankLogs[i - 1].data(), + rankLogs[i - 1].size()); + logFile += rankLogStr + "\n"; + } } - logFile += " }\n"; + logFile += "}\n"; + // write to file std::ofstream logStream(fileName); logStream.write(logFile.c_str(), logFile.size()); logStream.close(); diff --git a/source/utilities/format/bp1/BP1Writer.cpp b/source/utilities/format/bp1/BP1Writer.cpp index 30d393e9f088d9aa26f7ef2521af0abef12fc47e..69145b946d6476e7d71917f08c574d9c0e21f013 100644 --- a/source/utilities/format/bp1/BP1Writer.cpp +++ b/source/utilities/format/bp1/BP1Writer.cpp @@ -9,12 +9,13 @@ */ /// \cond EXCLUDE_FROM_DOXYGEN -#include "utilities/format/bp1/BP1Writer.h" - #include <string> #include <vector> /// \endcond +#include "BP1Writer.tcc" +#include "utilities/format/bp1/BP1Writer.h" + namespace adios { namespace format @@ -50,13 +51,13 @@ void BP1Writer::WriteProcessGroupIndex( // write if host language Fortran in metadata and data const char hostFortran = (isFortran) ? 'y' : 'n'; // if host language is fortran - CopyToBuffer(metadataBuffer, &hostFortran); - CopyToBuffer(dataBuffer, &hostFortran); + InsertToBuffer(metadataBuffer, &hostFortran); + InsertToBuffer(dataBuffer, &hostFortran); // write name in data WriteNameRecord(name, dataBuffer); // processID in metadata, - CopyToBuffer(metadataBuffer, &processID); + InsertToBuffer(metadataBuffer, &processID); // skip coordination var in data ....what is coordination var? dataBuffer.insert(dataBuffer.end(), 4, 0); @@ -66,33 +67,33 @@ void BP1Writer::WriteProcessGroupIndex( WriteNameRecord(timeStepName, dataBuffer); // time step to metadata and data - CopyToBuffer(metadataBuffer, &metadataSet.TimeStep); - CopyToBuffer(dataBuffer, &metadataSet.TimeStep); + InsertToBuffer(metadataBuffer, &metadataSet.TimeStep); + InsertToBuffer(dataBuffer, &metadataSet.TimeStep); // offset to pg in data in metadata which is the current absolute position - CopyToBuffer(metadataBuffer, reinterpret_cast<std::uint64_t *>( - &heap.m_DataAbsolutePosition)); + InsertToBuffer(metadataBuffer, reinterpret_cast<std::uint64_t *>( + &heap.m_DataAbsolutePosition)); // Back to writing metadata pg index length (length of group) const std::uint16_t metadataPGIndexLength = metadataBuffer.size() - metadataPGLengthPosition - 2; // without length of group record - CopyToBuffer(metadataBuffer, metadataPGLengthPosition, - &metadataPGIndexLength); + CopyToBufferPosition(metadataBuffer, metadataPGLengthPosition, + &metadataPGIndexLength); // DONE With metadataBuffer // here write method in data const std::vector<std::uint8_t> methodIDs = GetMethodIDs(transports); const std::uint8_t methodsCount = methodIDs.size(); - CopyToBuffer(dataBuffer, &methodsCount); // count + InsertToBuffer(dataBuffer, &methodsCount); // count const std::uint16_t methodsLength = methodIDs.size() * 3; // methodID (1) + method params length(2), no parameters for now - CopyToBuffer(dataBuffer, &methodsLength); // length + InsertToBuffer(dataBuffer, &methodsLength); // length for (const auto methodID : methodIDs) { - CopyToBuffer(dataBuffer, &methodID); // method ID, + InsertToBuffer(dataBuffer, &methodID); // method ID, dataBuffer.insert(dataBuffer.end(), 2, 0); // skip method params length = 0 (2 bytes) for now } @@ -161,7 +162,7 @@ std::string BP1Writer::GetRankProfilingLog( auto lf_WriterTimer = [](std::string &rankLog, const profiling::Timer &timer) { rankLog += "'" + timer.m_Process + "_" + timer.GetUnits() + "': " + - std::to_string(timer.m_ProcessTime) + ", "; + std::to_string(timer.m_ProcessTime); }; // prepare string dictionary per rank @@ -170,20 +171,36 @@ std::string BP1Writer::GetRankProfilingLog( auto &profiler = metadataSet.Log; rankLog += "'bytes': " + std::to_string(profiler.TotalBytes[0]) + ", "; lf_WriterTimer(rankLog, profiler.Timers[0]); + rankLog += ", "; for (unsigned int t = 0; t < transports.size(); ++t) { - auto &timers = transports[t]->m_Profiler.Timers; - rankLog += "'transport_" + std::to_string(t) + "': { "; - rankLog += "'lib': " + transports[t]->m_Type + ", "; + rankLog += "'lib': '" + transports[t]->m_Type + "', "; for (unsigned int i = 0; i < 3; ++i) - lf_WriterTimer(rankLog, timers[i]); + { + lf_WriterTimer(rankLog, transports[t]->m_Profiler.Timers[i]); + if (i < 2) + { + rankLog += ", "; + } + else + { + rankLog += " "; + } + } - rankLog += "}, "; + if (t == transports.size() - 1) // last element + { + rankLog += "}"; + } + else + { + rankLog += "},"; + } } - rankLog += "}, "; + rankLog += " },"; return rankLog; } @@ -197,9 +214,9 @@ void BP1Writer::WriteDimensionsRecord( { auto lf_WriteFlaggedDim = [](std::vector<char> &buffer, const char no, const std::size_t dimension) { - CopyToBuffer(buffer, &no); - CopyToBuffer(buffer, - reinterpret_cast<const std::uint64_t *>(&dimension)); + InsertToBuffer(buffer, &no); + InsertToBuffer(buffer, + reinterpret_cast<const std::uint64_t *>(&dimension)); }; // BODY Starts here @@ -220,8 +237,8 @@ void BP1Writer::WriteDimensionsRecord( { for (const auto &localDimension : localDimensions) { - CopyToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( - &localDimension)); + InsertToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( + &localDimension)); buffer.insert(buffer.end(), skip, 0); } } @@ -242,12 +259,12 @@ void BP1Writer::WriteDimensionsRecord( { for (unsigned int d = 0; d < localDimensions.size(); ++d) { - CopyToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( - &localDimensions[d])); - CopyToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( - &globalDimensions[d])); - CopyToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( - &globalOffsets[d])); + InsertToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( + &localDimensions[d])); + InsertToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( + &globalDimensions[d])); + InsertToBuffer(buffer, reinterpret_cast<const std::uint64_t *>( + &globalOffsets[d])); } } } @@ -257,8 +274,8 @@ void BP1Writer::WriteNameRecord(const std::string name, std::vector<char> &buffer) const noexcept { const std::uint16_t length = name.length(); - CopyToBuffer(buffer, &length); - CopyToBuffer(buffer, name.c_str(), length); + InsertToBuffer(buffer, &length); + InsertToBuffer(buffer, name.c_str(), length); } BP1Index & @@ -283,12 +300,13 @@ void BP1Writer::FlattenData(BP1MetadataSet &metadataSet, { auto &buffer = heap.m_Data; // vars count and Length (only for PG) - CopyToBuffer(buffer, metadataSet.DataPGVarsCountPosition, - &metadataSet.DataPGVarsCount); + CopyToBufferPosition(buffer, metadataSet.DataPGVarsCountPosition, + &metadataSet.DataPGVarsCount); const std::uint64_t varsLength = buffer.size() - metadataSet.DataPGVarsCountPosition - 8 - 4; // without record itself and vars count - CopyToBuffer(buffer, metadataSet.DataPGVarsCountPosition + 4, &varsLength); + CopyToBufferPosition(buffer, metadataSet.DataPGVarsCountPosition + 4, + &varsLength); // attributes (empty for now) count (4) and length (8) are zero by moving // positions in time step zero @@ -299,7 +317,8 @@ void BP1Writer::FlattenData(BP1MetadataSet &metadataSet, const std::uint64_t dataPGLength = buffer.size() - metadataSet.DataPGLengthPosition - 8; // without record itself, 12 due to empty attributes - CopyToBuffer(buffer, metadataSet.DataPGLengthPosition, &dataPGLength); + CopyToBufferPosition(buffer, metadataSet.DataPGLengthPosition, + &dataPGLength); ++metadataSet.TimeStep; metadataSet.DataPGIsOpen = false; @@ -318,7 +337,7 @@ void BP1Writer::FlattenMetadata(BP1MetadataSet &metadataSet, { auto &indexBuffer = indexPair.second.Buffer; const std::uint32_t indexLength = indexBuffer.size() - 4; - CopyToBuffer(indexBuffer, 0, &indexLength); + CopyToBufferPosition(indexBuffer, 0, &indexLength); length += indexBuffer.size(); // overall length } @@ -328,13 +347,13 @@ void BP1Writer::FlattenMetadata(BP1MetadataSet &metadataSet, [](const std::uint32_t count, const std::uint64_t length, const std::unordered_map<std::string, BP1Index> &indices, std::vector<char> &buffer) { - CopyToBuffer(buffer, &count); - CopyToBuffer(buffer, &length); + InsertToBuffer(buffer, &count); + InsertToBuffer(buffer, &length); for (const auto &indexPair : indices) // set each index length { const auto &indexBuffer = indexPair.second.Buffer; - CopyToBuffer(buffer, indexBuffer.data(), indexBuffer.size()); + InsertToBuffer(buffer, indexBuffer.data(), indexBuffer.size()); } }; @@ -362,9 +381,9 @@ void BP1Writer::FlattenMetadata(BP1MetadataSet &metadataSet, // strategy // write pg index - CopyToBuffer(buffer, &pgCount); - CopyToBuffer(buffer, &pgLength); - CopyToBuffer(buffer, metadataSet.PGIndex.Buffer.data(), pgLength); + InsertToBuffer(buffer, &pgCount); + InsertToBuffer(buffer, &pgLength); + InsertToBuffer(buffer, metadataSet.PGIndex.Buffer.data(), pgLength); // Vars indices lf_FlattenIndices(varsCount, varsLength, metadataSet.VarsIndices, buffer); // Attribute indices @@ -377,17 +396,17 @@ void BP1Writer::FlattenMetadata(BP1MetadataSet &metadataSet, const std::uint64_t offsetAttributeIndex = offsetVarsIndex + (varsLength + 12); - CopyToBuffer(buffer, &offsetPGIndex); - CopyToBuffer(buffer, &offsetVarsIndex); - CopyToBuffer(buffer, &offsetAttributeIndex); + InsertToBuffer(buffer, &offsetPGIndex); + InsertToBuffer(buffer, &offsetVarsIndex); + InsertToBuffer(buffer, &offsetAttributeIndex); // version if (IsLittleEndian()) { const std::uint8_t endian = 0; - CopyToBuffer(buffer, &endian); + InsertToBuffer(buffer, &endian); buffer.insert(buffer.end(), 2, 0); - CopyToBuffer(buffer, &m_Version); + InsertToBuffer(buffer, &m_Version); } else { @@ -399,5 +418,22 @@ void BP1Writer::FlattenMetadata(BP1MetadataSet &metadataSet, metadataSet.Log.TotalBytes.push_back(heap.m_DataAbsolutePosition); } +//------------------------------------------------------------------------------ +// Explicit instantiaiton of public tempaltes + +#define declare_template_instantiation(T) \ + template void BP1Writer::WriteVariablePayload( \ + const Variable<T> &variable, capsule::STLVector &heap, \ + const unsigned int nthreads) const noexcept; \ + \ + template void BP1Writer::WriteVariableMetadata( \ + const Variable<T> &variable, capsule::STLVector &heap, \ + BP1MetadataSet &metadataSet) const noexcept; + +ADIOS_FOREACH_TYPE_1ARG(declare_template_instantiation) +#undef declare_template_instantiation + +//------------------------------------------------------------------------------ + } // end namespace format } // end namespace adios diff --git a/source/utilities/format/bp1/BP1Writer.tcc b/source/utilities/format/bp1/BP1Writer.tcc new file mode 100644 index 0000000000000000000000000000000000000000..d516af9dcf52abaf3229d9cfce9a06c9201cf8c5 --- /dev/null +++ b/source/utilities/format/bp1/BP1Writer.tcc @@ -0,0 +1,306 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BP1Writer.tcc + * + * Created on: Apr 11, 2017 + * Author: wfg + */ +#ifndef BP1WRITER_TCC_ +#define BP1WRITER_TCC_ + +#include "utilities/format/bp1/BP1Writer.h" + +namespace adios +{ +namespace format +{ + +// PUBLIC +template <class T> +std::size_t BP1Writer::GetVariableIndexSize(const Variable<T> &variable) const + noexcept +{ + // size_t indexSize = varEntryLength + memberID + lengthGroupName + + // groupName + lengthVariableName + lengthOfPath + path + datatype + std::size_t indexSize = 23; // without characteristics + indexSize += variable.m_Name.size(); + + // characteristics 3 and 4, check variable number of dimensions + const std::size_t dimensions = + variable.DimensionsSize(); // commas in CSV + 1 + indexSize += 28 * dimensions; // 28 bytes per dimension + indexSize += 1; // id + + // characteristics, offset + payload offset in data + indexSize += 2 * (1 + 8); + // characteristic 0, if scalar add value, for now only allowing string + if (dimensions == 1) + { + indexSize += sizeof(T); + indexSize += 1; // id + // must have an if here + indexSize += 2 + variable.m_Name.size(); + indexSize += 1; // id + } + + // characteristic statistics + if (m_Verbosity == 0) // default, only min and max + { + indexSize += 2 * (sizeof(T) + 1); + indexSize += 1 + 1; // id + } + + return indexSize + 12; // extra 12 bytes in case of attributes + // need to add transform characteristics +} + +template <class T> +void BP1Writer::WriteVariableMetadata(const Variable<T> &variable, + capsule::STLVector &heap, + BP1MetadataSet &metadataSet) const + noexcept +{ + Stats<typename TypeInfo<T>::ValueType> stats = GetStats(variable); + + stats.TimeIndex = metadataSet.TimeStep; + // Get new Index or point to existing index + bool isNew = true; // flag to check if variable is new + BP1Index &varIndex = + GetBP1Index(variable.m_Name, metadataSet.VarsIndices, isNew); + stats.MemberID = varIndex.MemberID; + + // write metadata header in data and extract offsets + stats.Offset = heap.m_DataAbsolutePosition; + WriteVariableMetadataInData(variable, stats, heap); + stats.PayloadOffset = heap.m_DataAbsolutePosition; + + // write to metadata index + WriteVariableMetadataInIndex(variable, stats, isNew, varIndex); + + ++metadataSet.DataPGVarsCount; +} + +template <class T> +void BP1Writer::WriteVariablePayload(const Variable<T> &variable, + capsule::STLVector &heap, + const unsigned int nthreads) const noexcept +{ + // EXPENSIVE part, might want to use threads if large, serial for now + InsertToBuffer(heap.m_Data, variable.m_AppValues, variable.TotalSize()); + heap.m_DataAbsolutePosition += variable.PayLoadSize(); +} + +// PRIVATE +template <class T> +BP1Writer::Stats<typename TypeInfo<T>::ValueType> +BP1Writer::GetStats(const Variable<T> &variable) const noexcept +{ + Stats<typename TypeInfo<T>::ValueType> stats; + const std::size_t valuesSize = variable.TotalSize(); + + if (m_Verbosity == 0) + { + if (valuesSize >= 10000000) // ten million? this needs actual results + // //we can make decisions for threads + // based on valuesSize + GetMinMax(variable.m_AppValues, valuesSize, stats.Min, stats.Max, + m_Threads); // here we can add cores from constructor + else + GetMinMax(variable.m_AppValues, valuesSize, stats.Min, stats.Max); + } + return stats; +} + +template <class T> +void BP1Writer::WriteBoundsRecord(const bool isScalar, const Stats<T> &stats, + std::vector<char> &buffer, + std::uint8_t &characteristicsCounter, + const bool addLength) const noexcept +{ + if (isScalar == true) + { + WriteCharacteristicRecord(characteristic_value, stats.Min, buffer, + characteristicsCounter, + addLength); // stats.min = stats.max = value + return; + } + + if (m_Verbosity == 0) // default verbose + { + WriteCharacteristicRecord(characteristic_min, stats.Min, buffer, + characteristicsCounter, addLength); + WriteCharacteristicRecord(characteristic_max, stats.Max, buffer, + characteristicsCounter, addLength); + } +} + +template <class T> +void BP1Writer::WriteCharacteristicRecord(const std::uint8_t characteristicID, + const T &value, + std::vector<char> &buffer, + std::uint8_t &characteristicsCounter, + const bool addLength) const noexcept +{ + const std::uint8_t id = characteristicID; + InsertToBuffer(buffer, &id); + + if (addLength == true) + { + const std::uint16_t lengthOfCharacteristic = sizeof(T); // id + InsertToBuffer(buffer, &lengthOfCharacteristic); + } + + InsertToBuffer(buffer, &value); + ++characteristicsCounter; +} + +template <class T> +void BP1Writer::WriteVariableMetadataInData( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, + capsule::STLVector &heap) const noexcept +{ + auto &buffer = heap.m_Data; + + // for writing length at the end + const std::size_t varLengthPosition = buffer.size(); + + buffer.insert(buffer.end(), 8, 0); // skip var length (8) + InsertToBuffer(buffer, &stats.MemberID); // memberID + WriteNameRecord(variable.m_Name, buffer); // variable name + buffer.insert(buffer.end(), 2, 0); // skip path + const std::uint8_t dataType = GetDataType<T>(); // dataType + InsertToBuffer(buffer, &dataType); + constexpr char no = 'n'; // isDimension + InsertToBuffer(buffer, &no); + + // write variable dimensions + const std::uint8_t dimensions = variable.m_LocalDimensions.size(); + InsertToBuffer(buffer, &dimensions); // count + + // 27 is from 9 bytes for each: var y/n + local, var y/n + global dimension, + // var y/n + global offset, changed for characteristic + std::uint16_t dimensionsLength = 27 * dimensions; + InsertToBuffer(buffer, &dimensionsLength); // length + WriteDimensionsRecord(buffer, variable.m_LocalDimensions, + variable.m_GlobalDimensions, variable.m_Offsets, 18, + true); + + // CHARACTERISTICS + WriteVariableCharacteristics(variable, stats, buffer, true); + + // Back to varLength including payload size + const std::uint64_t varLength = buffer.size() - varLengthPosition + + variable.PayLoadSize() - + 8; // remove its own size + + CopyToBufferPosition(buffer, varLengthPosition, &varLength); // length + + heap.m_DataAbsolutePosition += + buffer.size() - varLengthPosition; // update absolute position to be + // used as payload position +} + +template <class T> +void BP1Writer::WriteVariableMetadataInIndex( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, const bool isNew, + BP1Index &index) const noexcept +{ + auto &buffer = index.Buffer; + + if (isNew == true) // write variable header (might be shared with + // attributes index) + { + buffer.insert(buffer.end(), 4, 0); // skip var length (4) + InsertToBuffer(buffer, &stats.MemberID); + buffer.insert(buffer.end(), 2, 0); // skip group name + WriteNameRecord(variable.m_Name, buffer); + buffer.insert(buffer.end(), 2, 0); // skip path + + const std::uint8_t dataType = GetDataType<T>(); + InsertToBuffer(buffer, &dataType); + + // Characteristics Sets Count in Metadata + index.Count = 1; + InsertToBuffer(buffer, &index.Count); + } + else // update characteristics sets count + { + const std::size_t characteristicsSetsCountPosition = + 15 + variable.m_Name.size(); + ++index.Count; + CopyToBufferPosition(buffer, characteristicsSetsCountPosition, + &index.Count); // test + } + + WriteVariableCharacteristics(variable, stats, buffer); +} + +template <class T> +void BP1Writer::WriteVariableCharacteristics( + const Variable<T> &variable, + const Stats<typename TypeInfo<T>::ValueType> &stats, + std::vector<char> &buffer, const bool addLength) const noexcept +{ + const std::size_t characteristicsCountPosition = + buffer.size(); // very important to track as writer is going back to + // this position + buffer.insert(buffer.end(), 5, + 0); // skip characteristics count(1) + length (4) + std::uint8_t characteristicsCounter = 0; + + // DIMENSIONS + std::uint8_t characteristicID = characteristic_dimensions; + InsertToBuffer(buffer, &characteristicID); + const std::uint8_t dimensions = variable.m_LocalDimensions.size(); + + if (addLength == true) + { + const std::int16_t lengthOfDimensionsCharacteristic = + 24 * dimensions + 3; // 24 = 3 local, global, offset x 8 bytes/each + InsertToBuffer(buffer, &lengthOfDimensionsCharacteristic); + } + + InsertToBuffer(buffer, &dimensions); // count + const std::uint16_t dimensionsLength = 24 * dimensions; + InsertToBuffer(buffer, &dimensionsLength); // length + WriteDimensionsRecord(buffer, variable.m_LocalDimensions, + variable.m_GlobalDimensions, variable.m_Offsets, 16, + addLength); + ++characteristicsCounter; + + // VALUE for SCALAR or STAT min, max for ARRAY + WriteBoundsRecord(variable.m_IsScalar, stats, buffer, + characteristicsCounter, addLength); + // TIME INDEX + WriteCharacteristicRecord(characteristic_time_index, stats.TimeIndex, + buffer, characteristicsCounter, addLength); + + if (addLength == false) // only in metadata offset and payload offset + { + WriteCharacteristicRecord(characteristic_offset, stats.Offset, buffer, + characteristicsCounter); + WriteCharacteristicRecord(characteristic_payload_offset, + stats.PayloadOffset, buffer, + characteristicsCounter); + } + // END OF CHARACTERISTICS + + // Back to characteristics count and length + CopyToBufferPosition(buffer, characteristicsCountPosition, + &characteristicsCounter); // count (1) + const std::uint32_t characteristicsLength = + buffer.size() - characteristicsCountPosition - 4 - + 1; // remove its own length (4) + characteristic counter (1) + + CopyToBufferPosition(buffer, characteristicsCountPosition + 1, + &characteristicsLength); // length +} + +} // end namespace format +} // end namespace adios + +#endif // BP1WRITER_TCC_ diff --git a/source/utilities/realtime/dataman/DataMan.cpp b/source/utilities/realtime/dataman/DataMan.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eedda8a3aaa0055d31bb1bf1e797895406727405 --- /dev/null +++ b/source/utilities/realtime/dataman/DataMan.cpp @@ -0,0 +1,79 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * DataMan.cpp + * + * Created on: Apr 12, 2017 + * Author: Jason Wang + */ + +#include "utilities/realtime/dataman/DataMan.h" + +namespace adios +{ +namespace realtime +{ + +int DataMan::init(json p_jmsg) { return 0; } + +int DataMan::put(const void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_putshape, + std::vector<size_t> p_varshape, std::vector<size_t> p_offset, + size_t p_timestep, int p_tolerance, int p_priority) +{ + return DataMan::put(p_data, p_doid, p_var, p_dtype, p_putshape, p_varshape, + p_offset, p_timestep, p_tolerance, p_priority); +} + +int DataMan::put(const void *p_data, json p_jmsg) +{ + put_begin(p_data, p_jmsg); + put_end(p_data, p_jmsg); + return 0; +} + +void DataMan::add_file(std::string p_method) {} + +void DataMan::add_stream(json p_jmsg) +{ + + std::string method; + + if (p_jmsg["method"] != nullptr) + method = p_jmsg["method"]; + + logging("Streaming method " + method + " added"); + + if (m_tolerance.size() < m_num_channels) + { + for (int i = 0; i < m_num_channels; i++) + { + m_tolerance.push_back(0); + } + } + if (m_priority.size() < m_num_channels) + { + for (int i = 0; i < m_num_channels; i++) + { + m_priority.push_back(100 / (i + 1)); + } + } + + auto man = get_man(method); + if (man) + { + man->init(p_jmsg); + this->add_next(method, man); + } + add_man_to_path("zfp", method); +} + +void DataMan::flush() { flush_next(); } + +int DataMan::get(void *p_data, json &p_jmsg) { return 0; } + +// end namespace realtime +} +// end namespace adios +} diff --git a/source/utilities/realtime/dataman/DataManBase.cpp b/source/utilities/realtime/dataman/DataManBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5081eba05fa813ab56d593a8eee2e9f270a32848 --- /dev/null +++ b/source/utilities/realtime/dataman/DataManBase.cpp @@ -0,0 +1,268 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * DataManBase.cpp + * + * Created on: Apr 12, 2017 + * Author: Jason Wang + */ + +#include "utilities/realtime/dataman/DataManBase.h" + +namespace adios +{ +namespace realtime +{ + +DataManBase::DataManBase() +{ + m_profiling["total_manager_time"] = 0.0f; + m_profiling["total_mb"] = 0.0f; + m_start_time = std::chrono::system_clock::now(); +} + +int DataManBase::put(const void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_putshape, + std::vector<size_t> p_varshape, + std::vector<size_t> p_offset, size_t p_timestep, + int p_tolerance, int p_priority) +{ + json msg; + msg["doid"] = p_doid; + msg["var"] = p_var; + msg["dtype"] = p_dtype; + msg["putshape"] = p_putshape; + msg["putbytes"] = product(p_putshape, dsize(p_dtype)); + msg["varshape"] = p_varshape; + msg["varbytes"] = product(p_varshape, dsize(p_dtype)); + msg["offset"] = p_offset; + msg["timestep"] = p_timestep; + msg["tolerance"] = p_tolerance; + msg["priority"] = p_priority; + return put(p_data, msg); +} + +int DataManBase::put_begin(const void *p_data, json &p_jmsg) +{ + check_shape(p_jmsg); + p_jmsg["profiling"] = m_profiling; + m_step_time = std::chrono::system_clock::now(); + return 0; +} + +int DataManBase::put_end(const void *p_data, json &p_jmsg) +{ + auto end = std::chrono::system_clock::now(); + std::chrono::duration<double> duration = end - m_step_time; + m_profiling["total_manager_time"] = + m_profiling["total_manager_time"].get<double>() + duration.count(); + m_profiling["total_mb"] = + m_profiling["total_mb"].get<size_t>() + + product(p_jmsg["varshape"], dsize(p_jmsg["dtype"])) / 1000000.0f; + duration = end - m_start_time; + m_profiling["total_workflow_time"] = duration.count(); + m_profiling["workflow_mbs"] = + m_profiling["total_mb"].get<double>() / + m_profiling["total_workflow_time"].get<double>(); + m_profiling["manager_mbs"] = + m_profiling["total_mb"].get<double>() / + m_profiling["total_manager_time"].get<double>(); + if (p_jmsg["compressed_size"] != nullptr) + p_jmsg["putbytes"] = p_jmsg["compressed_size"].get<size_t>(); + put_next(p_data, p_jmsg); + return 0; +} + +int DataManBase::get(void *p_data, std::string p_doid, std::string p_var, + std::string p_dtype, std::vector<size_t> p_getshape, + std::vector<size_t> p_varshape, + std::vector<size_t> p_offset, size_t p_timestep) +{ + json msg; + msg["doid"] = p_doid; + msg["var"] = p_var; + msg["dtype"] = p_dtype; + msg["getshape"] = p_getshape; + msg["varshape"] = p_varshape; + msg["offset"] = p_offset; + msg["timestep"] = p_timestep; + return get(p_data, msg); +} + +int DataManBase::get(void *p_data, std::string p_doid, std::string p_var, + std::string &p_dtype, std::vector<size_t> &p_varshape, + size_t &p_timestep) +{ + json msg; + msg["doid"] = p_doid; + msg["var"] = p_var; + return get(p_data, msg); +} + +void DataManBase::reg_callback( + std::function<void(const void *, std::string, std::string, std::string, + std::vector<size_t>)> + cb) +{ + if (m_next.size() == 0) + { + m_callback = cb; + } + else + { + for (auto i : m_next) + { + i.second->reg_callback(cb); + } + } +} + +void DataManBase::dump(const void *p_data, json p_jmsg, std::ostream &out) +{ + std::vector<size_t> p_varshape = + p_jmsg["varshape"].get<std::vector<size_t>>(); + std::string dtype = p_jmsg["dtype"]; + size_t length = p_jmsg["dumplength"].get<size_t>(); + size_t s = 0; + for (size_t i = 0; i < product(p_varshape, 1); i++) + { + s++; + out << ((float *)p_data)[i] << " "; + if (s == length) + { + out << std::endl; + s = 0; + } + } + out << std::endl; +} + +void DataManBase::add_next(std::string p_name, + std::shared_ptr<DataManBase> p_next) +{ + m_next[p_name] = p_next; +} + +void DataManBase::remove_next(std::string p_name) { m_next.erase(p_name); } + +bool DataManBase::have_next() +{ + if (m_next.size() == 0) + { + return false; + } + else + { + return true; + } +} + +void DataManBase::print_next(std::ostream &out) +{ + for (auto i : m_next) + { + out << i.second->name() << " -> "; + i.second->print_next(); + out << std::endl; + } +} + +bool DataManBase::auto_transform(const void *p_in, void *p_out, json &p_jmsg) +{ + if (p_jmsg["compression_method"] != nullptr) + { + auto method = p_jmsg["compression_method"]; + auto man = get_man(method); + if (man == nullptr) + { + logging("Library file for compression method " + + p_jmsg["compression_method"].dump() + " not found!"); + return false; + } + man->transform(p_in, p_out, p_jmsg); + p_jmsg.erase("compression_method"); + p_jmsg.erase("compression_rate"); + p_jmsg.erase("compressed_size"); + return true; + } + else + { + return false; + } +} + +void DataManBase::add_man_to_path(std::string p_new, std::string p_path) +{ + if (m_next.count(p_path) > 0) + { + auto man = get_man(p_new); + if (man) + { + man->add_next(p_path, m_next[p_path]); + this->add_next(p_new, man); + this->remove_next(p_path); + } + } +} + +int DataManBase::flush_next() +{ + for (auto i : m_next) + { + i.second->flush(); + } + return 0; +} + +int DataManBase::put_next(const void *p_data, json p_jmsg) +{ + for (auto i : m_next) + { + i.second->put(p_data, p_jmsg); + } + return 0; +} + +std::shared_ptr<DataManBase> DataManBase::get_man(std::string method) +{ + void *so = NULL; +#ifdef __APPLE__ + std::string dylibname = "lib" + method + "man.dylib"; + so = dlopen(dylibname.c_str(), RTLD_NOW); + if (so) + { + std::shared_ptr<DataManBase> (*func)() = NULL; + func = (std::shared_ptr<DataManBase>(*)())dlsym(so, "getMan"); + if (func) + { + return func(); + } + } +#endif + std::string soname = "lib" + method + "man.so"; + so = dlopen(soname.c_str(), RTLD_NOW); + if (so) + { + std::shared_ptr<DataManBase> (*func)() = NULL; + func = (std::shared_ptr<DataManBase>(*)())dlsym(so, "getMan"); + if (func) + { + return func(); + } + else + { + logging("getMan() not found in " + soname); + } + } + else + { + logging("Dynamic library " + soname + " not found in LD_LIBRARY_PATH"); + } + return nullptr; +} + +// end namespace realtime +} +// end namespace adios +}