Skip to content

Commit

Permalink
#2342: add communications to LBDataHolder test
Browse files Browse the repository at this point in the history
  • Loading branch information
cwschilly committed Sep 6, 2024
1 parent 9386580 commit a9ec85f
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 87 deletions.
62 changes: 32 additions & 30 deletions src/vt/vrt/collection/balance/lb_data_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,25 @@
namespace vt { namespace vrt { namespace collection { namespace balance {

void get_object_from_json_field_(
const nlohmann::json& field, nlohmann::json& object, bool& is_bitpacked) {
const nlohmann::json& field, nlohmann::json& object, bool& is_bitpacked,
bool& is_collection) {
if (field.find("id") != field.end()) {
object = field["id"];
is_bitpacked = true;
} else {
object = field["seq_id"];
is_bitpacked = false;
}
if (field.find("collection_id") != field.end()) {
is_collection = true;
} else {
is_collection = false;
}
}

ElementIDStruct get_elm_from_object_info_(
const nlohmann::json& object, bool is_bitpacked, bool is_migratable,
const nlohmann::json& home, const nlohmann::json& node) {
const nlohmann::json& home) {
using Field = uint64_t;

Field object_id;
Expand All @@ -75,36 +81,32 @@ ElementIDStruct get_elm_from_object_info_(
}

return elm::ElmIDBits::createCollectionImpl(
is_migratable, object_id, home, node);
is_migratable, object_id, home, theContext()->getNode());
}

ElementIDStruct
get_elm_from_comm_object_(const nlohmann::json& field, bool collection) {
get_elm_from_comm_object_(const nlohmann::json& field) {
// Get the object's id and determine if it is bit-encoded
nlohmann::json object;
bool is_bitpacked;
get_object_from_json_field_(field, object, is_bitpacked);
bool is_collection;
get_object_from_json_field_(field, object, is_bitpacked, is_collection);
vtAssertExpr(object.is_number());

// Create elm with encoded data
ElementIDStruct elm;

if (collection) {
// TODO: need to get actual object data
int home = 0;
int node = 0;
bool is_migratable = false;

if (is_collection) {
int home = field["home"];
bool is_migratable = field["migratable"];
elm = get_elm_from_object_info_(
object, is_bitpacked, is_migratable, home, node);
object, is_bitpacked, is_migratable, home);
} else {
elm = ElementIDStruct{object, theContext()->getNode()};
}

return elm;
}


void LBDataHolder::outputEntity(nlohmann::json& j, ElementIDStruct const& id) const {
j["type"] = "object";
j["id"] = id.id;
Expand Down Expand Up @@ -359,23 +361,23 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j)

if (etype == "object") {
nlohmann::json object;
bool is_bitpacked;
get_object_from_json_field_(task["entity"], object, is_bitpacked);
bool is_bitpacked, is_collection;
get_object_from_json_field_(task["entity"], object, is_bitpacked, is_collection);
vtAssertExpr(object.is_number());

// Creating elm from `tasks` field
ElementIDStruct elm;

if (
task["entity"].find("collection_id") != task["entity"].end() and
task["entity"].find("index") != task["entity"].end()) {
if (is_collection) {
elm = get_elm_from_object_info_(
object, is_bitpacked, is_migratable, home, node);
object, is_bitpacked, is_migratable, home);
auto cid = task["entity"]["collection_id"];
auto idx = task["entity"]["index"];
if (cid.is_number() && idx.is_array()) {
std::vector<uint64_t> arr = idx;
auto proxy = static_cast<VirtualProxyType>(cid);
this->node_idx_[elm] = std::make_tuple(proxy, arr);
if (task["entity"].find("index") != task["entity"].end()) {
auto idx = task["entity"]["index"];
if (cid.is_number() && idx.is_array()) {
std::vector<uint64_t> arr = idx;
auto proxy = static_cast<VirtualProxyType>(cid);
this->node_idx_[elm] = std::make_tuple(proxy, arr);
}
}
} else {
elm = ElementIDStruct{object, node};
Expand Down Expand Up @@ -449,8 +451,8 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j)
// TODO: passing false here (and below) avoids encoding
// any information into the obj ids, which preserves
// the original behavior
auto from_elm = get_elm_from_comm_object_(comm["from"], false);
auto to_elm = get_elm_from_comm_object_(comm["to"], false);
auto from_elm = get_elm_from_comm_object_(comm["from"]);
auto to_elm = get_elm_from_comm_object_(comm["to"]);

CommKey key(
CommKey::CollectionTag{},
Expand All @@ -467,7 +469,7 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j)
auto from_node = comm["from"]["id"];
vtAssertExpr(from_node.is_number());

auto to_elm = get_elm_from_comm_object_(comm["to"], false);
auto to_elm = get_elm_from_comm_object_(comm["to"]);

CommKey key(
CommKey::NodeToCollectionTag{},
Expand All @@ -482,7 +484,7 @@ LBDataHolder::LBDataHolder(nlohmann::json const& j)
vtAssertExpr(comm["from"]["type"] == "object");
vtAssertExpr(comm["to"]["type"] == "node");

auto from_elm = get_elm_from_comm_object_(comm["from"], false);
auto from_elm = get_elm_from_comm_object_(comm["from"]);

auto to_node = comm["to"]["id"];
vtAssertExpr(to_node.is_number());
Expand Down
173 changes: 116 additions & 57 deletions tests/unit/lb/test_lb_data_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,75 +45,134 @@
#include <vt/collective/startup.h>
#include <vt/vrt/collection/balance/lb_data_holder.h>

#include "test_harness.h"
#include "test_parallel_harness.h"

#include <nlohmann/json.hpp>

namespace vt { namespace tests { namespace unit { namespace lb {

using TestLBDataHolder = TestHarness;

nlohmann::json create_basic_json(std::string id_type, int id,
int home, int node, bool is_migratable) {
nlohmann::json j = {
{"metadata", {
{"rank", 0},
{"type", "LBDatafile"}
}},
{"phases", {
{
{"id", 0},
{"tasks", {
{
{"entity", {
{"collection_id", 7},
{"index", {0}},
{"home", home},
{id_type, id},
{"migratable", is_migratable},
{"type", "object"}
}},
{"node", node},
{"resource", "cpu"},
{"time", 0.5},
}
}}
}
}}
};

return j;
using TestLBDataHolder = TestParallelHarness;
using LBDataHolder = vt::vrt::collection::balance::LBDataHolder;

nlohmann::json create_entity_(std::string id_type, int id, int home, bool is_migratable) {
nlohmann::json entity = {
{id_type, id},
{"type", "object"},
{"collection_id", 7},
{"index", {0}},
{"home", home},
{"migratable", is_migratable},
};
return entity;
}

void test_data_holder_elms(int seq_id, int home, int node, bool is_migratable) {
// Determine encoded ID
auto elm = elm::ElmIDBits::createCollectionImpl(is_migratable, seq_id, home, node);
auto encoded_id = elm.id;
nlohmann::json create_json_(
std::string id_type, int id_1, int id_2, int home, int node,
bool is_migratable) {

auto entity_1 = create_entity_(id_type, id_1, home, is_migratable);
auto entity_2 = create_entity_(id_type, id_2, home, is_migratable);

// Generate JSON
nlohmann::json j = {
{"metadata", {{"rank", 0}, {"type", "LBDatafile"}}},
{"phases",
{{{"communications",
{{{"bytes", 2.0},
{"from", entity_1},
{"messages", 1},
{"to", entity_2},
{"type", "SendRecv"}}}},
{"id", 0},
{"tasks",
{
{
{"entity", entity_1},
{"node", node},
{"resource", "cpu"},
{"time", 0.5},
},
{
{"entity", entity_2},
{"node", node},
{"resource", "cpu"},
{"time", 0.5},
}
}
}}}
}
};

return j;
}

void test_data_holder_elms(int seq_id_1, int home, int node, bool is_migratable) {
// Create a second seq_id
auto seq_id_2 = seq_id_1 + 1;

// Determine encoded ID
auto elm_1 =
elm::ElmIDBits::createCollectionImpl(is_migratable, seq_id_1, home, node);
auto encoded_id_1 = elm_1.id;

// Create second encoded ID
auto elm_2 =
elm::ElmIDBits::createCollectionImpl(is_migratable, seq_id_2, home, node);
auto encoded_id_2 = elm_2.id;

// Create DataHolder and get resulting object elm
auto simple_json_id = create_json_(
"id", encoded_id_1, encoded_id_2, home, node, is_migratable);
auto dh_id = LBDataHolder(simple_json_id);

// Create new DataHolder using "seq_id" and get elm
auto simple_json_seq =
create_json_("seq_id", seq_id_1, seq_id_2, home, node, is_migratable);
auto dh_seq = LBDataHolder(simple_json_seq);

// Find both elms in each DataHolder
auto it_id_1 = dh_id.node_data_[0].find(elm_1);
auto it_seq_1 = dh_seq.node_data_[0].find(elm_1);
auto it_id_2 = dh_id.node_data_[0].find(elm_2);
auto it_seq_2 = dh_seq.node_data_[0].find(elm_2);

// Assert that both elms exist
ASSERT_NE(it_id_1, dh_id.node_data_[0].end());
ASSERT_NE(it_seq_1, dh_seq.node_data_[0].end());
ASSERT_NE(it_id_2, dh_id.node_data_[0].end());
ASSERT_NE(it_seq_2, dh_seq.node_data_[0].end());

// Compare the the elms in each DataHolder
EXPECT_EQ(it_id_1->first, elm_1);
EXPECT_EQ(it_seq_1->first, elm_1);
EXPECT_EQ(it_id_2->first, elm_2);
EXPECT_EQ(it_seq_2->first, elm_2);

// Create DataHolder and get resulting object elm
auto simple_json_id = create_basic_json("id", encoded_id, home, node, is_migratable);
auto dh_id = vt::vrt::collection::balance::LBDataHolder(simple_json_id);
auto elm_id = dh_id.node_data_[0].begin()->first;
// Check the communication data
auto comm_id = dh_id.node_comm_[0];
auto comm_key_id = comm_id.begin()->first;
auto comm_seq = dh_seq.node_comm_[0];
auto comm_key_seq = comm_seq.begin()->first;

// Create new DataHolder using "seq_id" and get elm
auto simple_json_seq = create_basic_json("seq_id", seq_id, home, node, is_migratable);
auto dh_seq = vt::vrt::collection::balance::LBDataHolder(simple_json_seq);
auto elm_seq = dh_seq.node_data_[0].begin()->first;
// Ensure that we get the same CommKey from both id types
EXPECT_EQ(comm_key_id, comm_key_seq);

// Assert that both elms are equal (have the same id)
EXPECT_EQ(elm_id, elm_seq);
EXPECT_EQ(elm_id, elm);
// Assert that both elms are present in the communication data
EXPECT_EQ(comm_key_id.fromObj(), elm_1);
EXPECT_EQ(comm_key_id.toObj(), elm_2);
EXPECT_EQ(comm_key_seq.fromObj(), elm_1);
EXPECT_EQ(comm_key_seq.toObj(), elm_2);
}

TEST_F(TestLBDataHolder, test_lb_data_holder_no_comms_object_id) {
// Run a variety of test cases (seq_id, home, node, is_migratable)
test_data_holder_elms(0,0,0,false);
test_data_holder_elms(0,0,0,true);
test_data_holder_elms(0,0,2,false);
test_data_holder_elms(0,0,1,true);
test_data_holder_elms(1,1,0,false);
test_data_holder_elms(2,1,9,true);
test_data_holder_elms(3,0,1,false);
TEST_F(TestLBDataHolder, test_lb_data_holder_object_id) {
// Run a variety of test cases (seq_id, home, node, is_migratable)
test_data_holder_elms(0, 0, 0, false);
test_data_holder_elms(0, 0, 0, true);
test_data_holder_elms(0, 0, 2, false);
test_data_holder_elms(0, 0, 1, true);
test_data_holder_elms(1, 1, 0, false);
test_data_holder_elms(2, 1, 1, true);
test_data_holder_elms(3, 0, 1, false);
}

}}}} // end namespace vt::tests::unit::lb

0 comments on commit a9ec85f

Please sign in to comment.