ornladios / ADIOS2

Next generation of ADIOS developed in the Exascale Computing Program
https://adios2.readthedocs.io/en/latest/index.html
Apache License 2.0
274 stars 127 forks source link

Local values are mis-interpreted as global arrays #2726

Open eschnett opened 3 years ago

eschnett commented 3 years ago

When I write a local value to a file and read it back in, it is mis-interpreted as a global array.

This code demonstrates this:

#include <adios2.h>

#include <iostream>

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &xs) {
  os << "[";
  for (const auto &x : xs)
    os << x << ",";
  os << "]";
  return os;
}

void bpwrite() {
  auto adios = adios2::ADIOS();
  auto io = adios.DeclareIO("IO");
  auto engine = io.Open("example-cxx.bp", adios2::Mode::Write);

  const auto gscalar =
      io.DefineVariable<double>("global scalar", {}, {}, {}, true);
  const auto lscalar = io.DefineVariable<double>(
      "local scalar", {adios2::LocalValueDim}, {}, {}, true);
  const auto garray =
      io.DefineVariable<double>("global array", {1}, {0}, {1}, true);
  const auto larray =
      io.DefineVariable<double>("local array", {}, {}, {1}, true);

  const double x = 247;
  engine.Put(gscalar, &x);
  engine.Put(lscalar, &x);
  engine.Put(garray, &x);
  engine.Put(larray, &x);
  engine.PerformPuts();
  engine.Close();
}

void bpread() {
  auto adios = adios2::ADIOS();
  auto io = adios.DeclareIO("IO");
  auto engine = io.Open("example-cxx.bp", adios2::Mode::Read);

  const auto analyze = [](const auto var) {
    std::cout << "name: " << var.Name() << "\n"
              << "  type: " << var.Type() << "\n"
              << "  shape id: " << var.ShapeID() << "\n"
              << "  shape: " << var.Shape() << "\n"
              << "  shape: " << var.Start() << "\n"
              << "  shape: " << var.Count() << "\n";
  };

  auto gscalar = io.InquireVariable<double>("global scalar");
  auto lscalar = io.InquireVariable<double>("local scalar");
  auto garray = io.InquireVariable<double>("global array");
  auto larray = io.InquireVariable<double>("local array");
  analyze(gscalar);
  analyze(lscalar);
  analyze(garray);
  analyze(larray);

  engine.Close();
}

int main(int argc, char **argv) {
  bpwrite();
  bpread();
  return 0;
}

The output is:

name: global scalar
  type: double
  shape id: ShapeID::GlobalValue
  shape: []
  shape: []
  shape: []
name: local scalar
  type: double
  shape id: ShapeID::GlobalArray
  shape: [1,]
  shape: [0,]
  shape: [1,]
name: global array
  type: double
  shape id: ShapeID::GlobalArray
  shape: [1,]
  shape: [0,]
  shape: [1,]
name: local array
  type: double
  shape id: ShapeID::LocalArray
  shape: []
  shape: []
  shape: [1,]
  double   global array   {1}
  double   global scalar  scalar
  double   local array    [1]*{1}
  double   local scalar   {1}

Note the variable called local value, which has the shape id GlobalArray.

williamfgc commented 3 years ago

When I write a local value to a file and read it back in, it is mis-interpreted as a global array.

Since local values is a N-values-to-1-variable write operation, the reader gets confused going from 1-variable-to-N-values if we are to return a single local value. The design decision was to expose them as a global array so readers can easily distinguish between local values as they are assembled. Typical examples are "per-rank" values that are independent (they could easily be a 1D global array): timing per rank, rankID itself, number of cells per rank, etc. The documentation has to be more clear, though. Thanks for bringing it up. Hope it helps.