Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Vector inputs to a task #124

Open
josephjohnjj opened this issue Jul 1, 2021 · 8 comments
Open

Vector inputs to a task #124

josephjohnjj opened this issue Jul 1, 2021 · 8 comments

Comments

@josephjohnjj
Copy link

I have a task that takes a std::vector<Octant_Aggregator_Data> as input

auto make_test(ttg::Edge<Key, std::vector<Octant_Aggregator_Data>>& testEdge) 
{
  auto f = [=](const Key& key, std::vector<Octant_Aggregator_Data>& testData, std::tuple<>& out)
            {
              printf("==========TEST========  \n"); 
            };
            
  return ttg::wrap<Key>(f, ttg::edges(testEdge), ttg::edges(), "test", {"testEdge"}, {});
} 

The class Octant_Aggregator_Data is as follows

struct Octant_Aggregator_Data
{
  Key octant_key;
  Key parent_key;
  int next_level;

  Octant_Aggregator_Data() = default;
  Octant_Aggregator_Data(Key key1, Key key2, int level) : 
    octant_key(key1), parent_key(key2), next_level(level){}

  bool operator==(const Octant_Aggregator_Data& b) const 
      { return octant_key == b.octant_key && parent_key == b.parent_key && next_level == b.next_level; }
      
  bool operator!=(const Octant_Aggregator_Data& b) const { return !((*this) == b); }

  Key get_octant_key() const { return octant_key; }
  Key get_parent_key() const { return parent_key; }
  int get_next_level() const { return next_level; }

  void set_octant_key(Key key)  { octant_key = key; }
  void set_parent_key(Key key)  { parent_key = key; }
  void set_next_level(int value) { next_level = value; }

  //template <typename Archive>
  //void serialize(Archive& ar) {
  //  ar& madness::archive::wrap((unsigned char*)this, sizeof(*this));
  //}

};

I followed ttg/examples/randomaccess/randomaccess.cc to serialise the object of this class:

namespace madness {
  namespace archive {
    template <class Archive>
      struct ArchiveStoreImpl<Archive, Octant_Aggregator_Data> {
        static inline void store(const Archive& ar, const Octant_Aggregator_Data& d) {
          ar << d.get_octant_key() << d.get_parent_key() << d.get_next_level();
          ar << wrap(&d, sizeof(Octant_Aggregator_Data));
        }
      };

    template <class Archive>
      struct ArchiveLoadImpl<Archive, Octant_Aggregator_Data> {
        static inline void load(const Archive& ar, Octant_Aggregator_Data& d) {
          Key octant_key;
          Key parent_key;
          int next_level;
          ar >> octant_key >> parent_key >> next_level;
          d = Octant_Aggregator_Data(octant_key, parent_key, next_level);
          ar >> wrap(&d, sizeof(Octant_Aggregator_Data));
        }
      };
  }
}

but I get the error

../examples/miniamr/miniamr.cc:565:88:   required from here
../ttg/ttg/parsec/ttg.h:546:21: error: incomplete type ‘ttg::default_data_descriptor<std::vector<Octant_Aggregator_Data>, void>’ used in nested name specifier
  546 |       if constexpr (!ttg::default_data_descriptor<ttg::meta::remove_cvr_t<T>>::serialize_size_is_const) {
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../ttg/ttg/parsec/ttg.h: In instantiation of ‘uint64_t ttg_parsec::Op<keyT, output_terminalsT, derivedT, input_valueTs>::pack(T&, void*, uint64_t) [with T = const std::vector<Octant_Aggregator_Data>; keyT = Key; output_terminalsT = std::tuple<>; derivedT = ttg_parsec::WrapOpArgs<make_test(ttg::Edge<Key, std::vector<Octant_Aggregator_Data> >&)::<lambda(const Key&, std::vector<Octant_Aggregator_Data>&, std::tuple<>&)>&, Key, std::tuple<>, std::vector<Octant_Aggregator_Data, std::allocator<Octant_Aggregator_Data> > >; input_valueTs = {std::vector<Octant_Aggregator_Data, std::allocator<Octant_Aggregator_Data> >}; uint64_t = long unsigned int]’:

Are there any problems with the load() and store() function here?

@josephjohnjj josephjohnjj changed the title Vector inputs to a task: incomplete type ‘ttg::default_data_descriptor<std::vector<Octant_Aggregator_Data>, void>’ used in nested name specifier Vector inputs to a task Jul 1, 2021
@devreal
Copy link
Contributor

devreal commented Jul 1, 2021

@evaleev we don't support vectors of madness-serializable types? I though that was transitive

@josephjohnjj
Copy link
Author

So there is no need for load() and store() functions?

@evaleev
Copy link
Contributor

evaleev commented Jul 5, 2021

@josephjohnjj I can't reproduce the issue ... could you please show the complete example?

Here's what I can compile successfully:

#define WORLD_INSTANTIATE_STATIC_TEMPLATES
#define TTG_USE_MADNESS 1
#include "ttg.h"
#include <catch2/catch.hpp>

struct Key {
  int i[3];
  bool operator==(const Key& other) const {
    return i[0] == other.i[0] && i[1] == other.i[1] && i[2] == other.i[2];
  }
};

std::ostream& operator<<(std::ostream& os, const Key& key) {
  os << key.i[0] << " " << key.i[1] << " " << key.i[2];
  return os;
}

struct Octant_Aggregator_Data
{
  Key octant_key;
  Key parent_key;
  int next_level;

  Octant_Aggregator_Data() = default;
  Octant_Aggregator_Data(Key key1, Key key2, int level) :
      octant_key(key1), parent_key(key2), next_level(level){}

  bool operator==(const Octant_Aggregator_Data& b) const
  { return octant_key == b.octant_key && parent_key == b.parent_key && next_level == b.next_level; }

  bool operator!=(const Octant_Aggregator_Data& b) const { return !((*this) == b); }

  Key get_octant_key() const { return octant_key; }
  Key get_parent_key() const { return parent_key; }
  int get_next_level() const { return next_level; }

  void set_octant_key(Key key)  { octant_key = key; }
  void set_parent_key(Key key)  { parent_key = key; }
  void set_next_level(int value) { next_level = value; }

  //template <typename Archive>
  //void serialize(Archive& ar) {
  //  ar& madness::archive::wrap((unsigned char*)this, sizeof(*this));
  //}

};

namespace madness {
  namespace archive {
    template <class Archive>
    struct ArchiveStoreImpl<Archive, Octant_Aggregator_Data> {
      static inline void store(const Archive& ar, const Octant_Aggregator_Data& d) {
        ar << d.get_octant_key() << d.get_parent_key() << d.get_next_level();
        ar << wrap(&d, sizeof(Octant_Aggregator_Data));
      }
    };

    template <class Archive>
    struct ArchiveLoadImpl<Archive, Octant_Aggregator_Data> {
      static inline void load(const Archive& ar, Octant_Aggregator_Data& d) {
        Key octant_key;
        Key parent_key;
        int next_level;
        ar >> octant_key >> parent_key >> next_level;
        d = Octant_Aggregator_Data(octant_key, parent_key, next_level);
        ar >> wrap(&d, sizeof(Octant_Aggregator_Data));
      }
    };
  }
}

//static_assert(!ttg::default_data_descriptor<std::vector<Octant_Aggregator_Data>>::serialize_size_is_const);

auto make_test(ttg::Edge<Key, std::vector<Octant_Aggregator_Data>>& testEdge)
{
  auto f = [=](const Key& key, std::vector<Octant_Aggregator_Data>& testData, std::tuple<>& out)
            {
              printf("==========TEST========  \n");
            };

  return ttg::wrap<Key>(f, ttg::edges(testEdge), ttg::edges(), "test", {"testEdge"}, {});
}

TEST_CASE("issue 124", "[issues]") {
  ttg::Edge<Key, std::vector<Octant_Aggregator_Data>> edge;
  auto op = make_test(edge);
  op->invoke(Key{0,0,0}, std::vector<Octant_Aggregator_Data>{});
}

@josephjohnjj
Copy link
Author

josephjohnjj commented Jul 6, 2021

#include <array>
#include <cmath>
#include <cstdio>
#include "ttg.h"
using namespace ttg;
#include <madness/world/world.h>

int d = 6;

struct Key {
  // (x, y, z, l, ts) where (x, y, z) is the cartesian coordinate of the anchor
  //                    l is the level of the block in the octree
  //                    ts is the timestep
    

  int x = -1, y = -1, z = -1, l = -1, ts = -1;
  madness::hashT hash_val;

  Key() { morton_3d_rehash(); }
  Key(int x, int y, int z, int l, int ts) : x(x), y(y), z(z), l(l), ts(ts) 
  { 
    morton_3d_rehash(); 
  }

  madness::hashT hash() const { return hash_val; }


  inline int morton_3d_rehash()
  {
    int X = x, Y = y, Z = z;
    X = (X | (X << 16)) & 0x030000FF;
    X = (X | (X <<  8)) & 0x0300F00F;
    X = (X | (X <<  4)) & 0x030C30C3;
    X = (X | (X <<  2)) & 0x09249249;

    Y = (Y | (Y << 16)) & 0x030000FF;
    Y = (Y | (Y <<  8)) & 0x0300F00F;
    Y = (Y | (Y <<  4)) & 0x030C30C3;
    Y = (Y | (Y <<  2)) & 0x09249249;

    Z = (Z | (Z << 16)) & 0x030000FF;
    Z = (Z | (Z <<  8)) & 0x0300F00F;
    Z = (Z | (Z <<  4)) & 0x030C30C3;
    Z = (Z | (Z <<  2)) & 0x09249249;

    int morton = X | (Y << 1) | (Z << 2);
    hash_val = ( morton << (d-1) ) | l;
    return 1;
  }


  // Equality test
  bool operator==(const Key& b) const { return (x == b.x && y == b.y && z == b.z && l == b.l && ts == b.ts); }
  // Inequality test
  bool operator!=(const Key& b) const { return !((*this) == b); }

  //less than operator
  bool operator<(const Key& b) const 
  { 
    if( (hash_val + ts) < (b.hash_val + b.ts) )
      return true;
    else
      return false;

  }

  template <typename Archive>
  void serialize(Archive& ar) {
    ar& madness::archive::wrap((unsigned char*)this, sizeof(*this));
  }
};

struct Octant_Aggregator_Data
{
  Key octant_key;
  Key parent_key;
  int next_level;

  Octant_Aggregator_Data() = default;
  Octant_Aggregator_Data(Key key1, Key key2, int level) :
      octant_key(key1), parent_key(key2), next_level(level){}

  bool operator==(const Octant_Aggregator_Data& b) const
  { return octant_key == b.octant_key && parent_key == b.parent_key && next_level == b.next_level; }

  bool operator!=(const Octant_Aggregator_Data& b) const { return !((*this) == b); }

  Key get_octant_key() const { return octant_key; }
  Key get_parent_key() const { return parent_key; }
  int get_next_level() const { return next_level; }

  void set_octant_key(Key key)  { octant_key = key; }
  void set_parent_key(Key key)  { parent_key = key; }
  void set_next_level(int value) { next_level = value; }

  //template <typename Archive>
  //void serialize(Archive& ar) {
  //  ar& madness::archive::wrap((unsigned char*)this, sizeof(*this));
  //}

};

namespace madness {
  namespace archive {
    template <class Archive>
    struct ArchiveStoreImpl<Archive, Octant_Aggregator_Data> {
      static inline void store(const Archive& ar, const Octant_Aggregator_Data& d) {
        ar << d.get_octant_key() << d.get_parent_key() << d.get_next_level();
        ar << wrap(&d, sizeof(Octant_Aggregator_Data));
      }
    };

    template <class Archive>
    struct ArchiveLoadImpl<Archive, Octant_Aggregator_Data> {
      static inline void load(const Archive& ar, Octant_Aggregator_Data& d) {
        Key octant_key;
        Key parent_key;
        int next_level;
        ar >> octant_key >> parent_key >> next_level;
        d = Octant_Aggregator_Data(octant_key, parent_key, next_level);
        ar >> wrap(&d, sizeof(Octant_Aggregator_Data));
      }
    };
  }
}

auto make_test(ttg::Edge<Key, std::vector<Octant_Aggregator_Data>>& testEdge)
{
  auto f = [=](const Key& key, std::vector<Octant_Aggregator_Data>& testData, std::tuple<>& out)
            {
              printf("==========TEST========  \n");
            };

  return ttg::wrap<Key>(f, ttg::edges(testEdge), ttg::edges(), "test", {"testEdge"}, {});
}



int main(int argc, char** argv) 
{
  
  ttg::ttg_initialize(argc, argv, -1);
  auto world = ttg::ttg_default_execution_context();

  ttg::Edge<Key, std::vector<Octant_Aggregator_Data>> edge;
  auto op = make_test(edge);

  auto connected = make_graph_executable(op.get());
  assert(connected);
  TTGUNUSED(connected);
  std::cout << "Graph is connected: " << connected << std::endl;

  if (world.rank() == 0) 
  {
    op->invoke(Key{0, 0, 0, 0, 0}, std::vector<Octant_Aggregator_Data>{});
  }

  ttg::ttg_execute(world);
  ttg::ttg_fence(world);
  ttg::ttg_finalize();

  return 0;
}

compile.txt

@therault
Copy link
Contributor

therault commented Jul 9, 2021

Joseph, can you try with a compiler that is more recent? Do you have clang 11 or 12?

@evaleev
Copy link
Contributor

evaleev commented Jul 9, 2021

@josephjohnjj

if I add

std::ostream& operator<<(std::ostream& os, const Key& key) {
  os << "{" << key.x << " " << key.y << " " << key.z << " " << key.l << " " << key.ts << "}";
  return os;
}

then everything compiles on my Mac with clang (apple) and gcc 11. I suspect compiler bug.

@josephjohnjj
Copy link
Author

I added the code suggested by @evaleev and compiled using clang, but I get a different set of errors.
clang.txt

@devreal
Copy link
Contributor

devreal commented Oct 29, 2021

@josephjohnjj What is the status of this? Is it still failing with current master?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants