From e0848f9489f5eda876909ef2e9085abf2d3a6dfd Mon Sep 17 00:00:00 2001 From: Robert Chisholm Date: Mon, 11 Jul 2022 14:42:57 +0100 Subject: [PATCH] Initial tests and fixes. --- .../EnvironmentDirectedGraphDescription.cuh | 8 +- .../EnvironmentDirectedGraphCUDABuffers.cu | 6 +- tests/CMakeLists.txt | 1 + .../test_environment_directed_graph.cu | 201 ++++++++++++++++++ 4 files changed, 209 insertions(+), 7 deletions(-) create mode 100644 tests/test_cases/runtime/test_environment_directed_graph.cu diff --git a/include/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphDescription.cuh b/include/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphDescription.cuh index a36a9cada..614c249a2 100644 --- a/include/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphDescription.cuh +++ b/include/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphDescription.cuh @@ -212,7 +212,7 @@ void EnvironmentDirectedGraph::Description::newVertexProperty(const std::string& if (graph->vertexProperties.find(property_name) == graph->vertexProperties.end()) { const std::array::type_t, type_decode::len_t* N>* casted_default = reinterpret_cast::type_t, type_decode::len_t* N>*>(&default_value); - graph->vertexProperties.emplace(property_name, property(*casted_default)); + graph->vertexProperties.emplace(property_name, Variable(*casted_default)); return; } THROW exception::InvalidGraphProperty("Graph ('%s') already contains vertex property '%s', " @@ -234,7 +234,7 @@ void EnvironmentDirectedGraph::Description::newEdgeProperty(const std::string& p if (graph->edgeProperties.find(property_name) == graph->edgeProperties.end()) { const std::array::type_t, type_decode::len_t* N>* casted_default = reinterpret_cast::type_t, type_decode::len_t* N>*>(&default_value); - graph->edgeProperties.emplace(property_name, property(*casted_default)); + graph->edgeProperties.emplace(property_name, Variable(*casted_default)); return; } THROW exception::InvalidGraphProperty("Graph ('%s') already contains edge property '%s', " @@ -262,7 +262,7 @@ void EnvironmentDirectedGraph::Description::newVertexPropertyArray(const std::st if (default_value.size()) { memcpy(temp.data(), default_value.data(), sizeof(typename type_decode::type_t) * type_decode::len_t * length); } - graph->vertexProperties.emplace(property_name, property(type_decode::len_t * length, temp)); + graph->vertexProperties.emplace(property_name, Variable(type_decode::len_t * length, temp)); return; } THROW exception::InvalidGraphProperty("Graph ('%s') already contains vertex property '%s', " @@ -289,7 +289,7 @@ void EnvironmentDirectedGraph::Description::newEdgePropertyArray(const std::stri if (default_value.size()) { memcpy(temp.data(), default_value.data(), sizeof(typename type_decode::type_t) * type_decode::len_t * length); } - graph->edgeProperties.emplace(property_name, property(type_decode::len_t * length, temp)); + graph->edgeProperties.emplace(property_name, Variable(type_decode::len_t * length, temp)); return; } THROW exception::InvalidGraphProperty("Graph ('%s') already contains edge property '%s', " diff --git a/src/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphCUDABuffers.cu b/src/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphCUDABuffers.cu index b44dffda8..23f0efe53 100644 --- a/src/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphCUDABuffers.cu +++ b/src/flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphCUDABuffers.cu @@ -40,7 +40,7 @@ void EnvironmentDirectedGraph::CUDABuffers::allocateVertexBuffers(const size_typ THROW exception::UnknownInternalError("Device buffer already allocated, in EnvironmentDirectedGraph::CUDABuffers::allocateVertexBuffers()"); } if (!vb.h_ptr) { - vb.h_ptr = malloc(vertex_count * v.second.type_size * v.second.elements); + vb.h_ptr = malloc(count * v.second.type_size * v.second.elements); } else { THROW exception::UnknownInternalError("Host buffer already allocated, in EnvironmentDirectedGraph::CUDABuffers::allocateVertexBuffers()"); } @@ -65,7 +65,7 @@ void EnvironmentDirectedGraph::CUDABuffers::allocateEdgeBuffers(const size_type THROW exception::UnknownInternalError("Device buffer already allocated, in EnvironmentDirectedGraph::CUDABuffers::allocateEdgeBuffers()"); } if (!eb.h_ptr) { - eb.h_ptr = malloc(edge_count * e.second.type_size * e.second.elements); + eb.h_ptr = malloc(count * e.second.type_size * e.second.elements); } else { THROW exception::UnknownInternalError("Host buffer already allocated, in EnvironmentDirectedGraph::CUDABuffers::allocateEdgeBuffers()"); } @@ -129,7 +129,7 @@ void EnvironmentDirectedGraph::CUDABuffers::setEdgeCount(const size_type count) auto& eb = edge_buffers.at(e.first); eb.device_ready = false; // Possibly faster if we checked default_value == 0 and memset, but awkward with vague type and lack of template - for (unsigned int i = 0; i < vertex_count; ++i) { + for (unsigned int i = 0; i < edge_count; ++i) { memcpy(static_cast(eb.h_ptr) + i * e.second.type_size * e.second.elements, e.second.default_value, e.second.type_size * e.second.elements); } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 09e49ed7e..7b48d9aae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -43,6 +43,7 @@ SET(TESTS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_device_api.cu ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_device_environment.cu ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_device_macro_property.cu + ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_environment_directed_graph.cu ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_environment_manager.cu ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_host_api.cu ${CMAKE_CURRENT_SOURCE_DIR}/test_cases/runtime/test_host_agent_sort.cu diff --git a/tests/test_cases/runtime/test_environment_directed_graph.cu b/tests/test_cases/runtime/test_environment_directed_graph.cu new file mode 100644 index 000000000..81bbb57a2 --- /dev/null +++ b/tests/test_cases/runtime/test_environment_directed_graph.cu @@ -0,0 +1,201 @@ +/** + * Tests of: Environment Directed Graph functionality + * This combines testing of all features as they are quite tightly linked + * + * Tests cover: + * > Host set/get + * > Host get default + * > Device get + * > Device get default + * > Host validation (todo) + * > Device validation (todo) + */ + +#include "flamegpu/flamegpu.h" +#include "flamegpu/runtime/environment/EnvironmentDirectedGraph/EnvironmentDirectedGraphDescription.cuh" + +#include "gtest/gtest.h" + +namespace flamegpu { +const unsigned int EDGE_COUNT = 10; +const unsigned int VERTEX_COUNT = 10; +FLAMEGPU_HOST_FUNCTION(hostfn_HostSetGet_Edge) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setEdgeCount(EDGE_COUNT); + // Check default matches + for (unsigned int i = 0; i < EDGE_COUNT; ++i) { + EXPECT_EQ(graph.getEdgeProperty("edge", i), 12.0f); + } + // Set all values + for (unsigned int i = 0; i < EDGE_COUNT; ++i) { + graph.setEdgeProperty("edge", i, 14.0f + i); + } + // Check set values match + for (unsigned int i = 0; i < EDGE_COUNT; ++i) { + EXPECT_EQ(graph.getEdgeProperty("edge", i), 14.0f + i); + } + graph.setEdgeCount(EDGE_COUNT * 2); + // Check default matches + for (unsigned int i = 0; i < EDGE_COUNT * 2; ++i) { + EXPECT_EQ(graph.getEdgeProperty("edge", i), 12.0f); + } +} +TEST(EnvironmentDirectedGraphTest, HostSetGet_Edge) { + ModelDescription model("test"); + model.newAgent("agent"); + auto &graph = model.Environment().newDirectedGraph("graph"); + graph.newEdgeProperty("edge", 12.0f); + model.newLayer().addHostFunction(hostfn_HostSetGet_Edge); +} + +FLAMEGPU_HOST_FUNCTION(hostfn_HostSetGet_Vertex) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setVertexCount(VERTEX_COUNT); + // Check default matches + for (unsigned int i = 0; i < VERTEX_COUNT; ++i) { + EXPECT_EQ(graph.getVertexProperty("vertex", i), 12.0f); + } + // Set all values + for (unsigned int i = 0; i < VERTEX_COUNT; ++i) { + graph.setVertexProperty("vertex", i, 14 + static_cast(i)); + } + // Check set values match + for (unsigned int i = 0; i < VERTEX_COUNT; ++i) { + EXPECT_EQ(graph.getVertexProperty("vertex", i), 14.0f + i); + } + graph.setVertexCount(VERTEX_COUNT * 2); + // Check default matches + for (unsigned int i = 0; i < VERTEX_COUNT * 2; ++i) { + EXPECT_EQ(graph.getVertexProperty("vertex", i), 12.0f); + } +} +TEST(EnvironmentDirectedGraphTest, HostSetGet_Vertex) { + ModelDescription model("test"); + model.newAgent("agent"); + auto& graph = model.Environment().newDirectedGraph("graph"); + graph.newVertexProperty("vertex", 5); + model.newLayer().addHostFunction(hostfn_HostSetGet_Edge); +} +FLAMEGPU_HOST_FUNCTION(hostfn_DeviceGet_Edge) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setEdgeCount(EDGE_COUNT); + // Set all values + for (unsigned int i = 0; i < EDGE_COUNT; ++i) { + graph.setEdgeProperty("edge", i, 14.0f + i); + } +} +FLAMEGPU_AGENT_FUNCTION(DeviceGet_Edge, MessageNone, MessageNone) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + const float t = graph.getEdgeProperty("edge", FLAMEGPU->getThreadIndex()); + FLAMEGPU->setVariable("tid", FLAMEGPU->getThreadIndex()); + FLAMEGPU->setVariable("edge_value", t); + return flamegpu::ALIVE; +} +TEST(EnvironmentDirectedGraphTest, DeviceGet_Edge) { + ModelDescription model("test"); + auto &agent = model.newAgent("agent"); + agent.newVariable("edge_value", 0.0f); + agent.newVariable("tid", 0); + agent.newFunction("DeviceGet_Edge", DeviceGet_Edge); + auto& graph = model.Environment().newDirectedGraph("graph"); + graph.newEdgeProperty("edge", 12.0f); + model.newLayer().addHostFunction(hostfn_DeviceGet_Edge); + model.newLayer().addAgentFunction(DeviceGet_Edge); + + CUDASimulation sim(model); + AgentVector pop(agent, EDGE_COUNT); + sim.setPopulationData(pop); + sim.step(); + sim.getPopulationData(pop); + // Check result matches + for (const auto &p : pop) { + EXPECT_EQ(p.getVariable("edge_value"), 14.0f + p.getVariable("tid")); + } +} +FLAMEGPU_HOST_FUNCTION(hostfn_DeviceGetDefault_Edge) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setEdgeCount(EDGE_COUNT); +} +TEST(EnvironmentDirectedGraphTest, DeviceGetDefault_Edge) { + ModelDescription model("test"); + auto& agent = model.newAgent("agent"); + agent.newVariable("edge_value", 0.0f); + agent.newVariable("tid", 0); + agent.newFunction("DeviceGet_Edge", DeviceGet_Edge); + auto& graph = model.Environment().newDirectedGraph("graph"); + graph.newEdgeProperty("edge", 12.0f); + model.newLayer().addHostFunction(hostfn_DeviceGetDefault_Edge); + model.newLayer().addAgentFunction(DeviceGet_Edge); + + CUDASimulation sim(model); + AgentVector pop(agent, EDGE_COUNT); + sim.setPopulationData(pop); + sim.step(); + sim.getPopulationData(pop); + // Check result matches + for (const auto& p : pop) { + EXPECT_EQ(p.getVariable("edge_value"), 12.0f); + } +} +FLAMEGPU_HOST_FUNCTION(hostfn_DeviceGet_Vertex) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setVertexCount(VERTEX_COUNT); + // Set all values + for (unsigned int i = 0; i < VERTEX_COUNT; ++i) { + graph.setVertexProperty("vertex", i, 14 + static_cast(i)); + } +} +FLAMEGPU_AGENT_FUNCTION(DeviceGet_Vertex, MessageNone, MessageNone) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + const float t = graph.getVertexProperty("vertex", FLAMEGPU->getThreadIndex()); + FLAMEGPU->setVariable("tid", FLAMEGPU->getThreadIndex()); + FLAMEGPU->setVariable("vertex_value", t); + return flamegpu::ALIVE; +} +TEST(EnvironmentDirectedGraphTest, DeviceGet_Vertex) { + ModelDescription model("test"); + auto& agent = model.newAgent("agent"); + agent.newVariable("vertex_value", 0u); + agent.newVariable("tid", 0); + agent.newFunction("DeviceGet_Vertex", DeviceGet_Vertex); + auto& graph = model.Environment().newDirectedGraph("graph"); + graph.newVertexProperty("vertex", 12); + model.newLayer().addHostFunction(hostfn_DeviceGet_Vertex); + model.newLayer().addAgentFunction(DeviceGet_Vertex); + + CUDASimulation sim(model); + AgentVector pop(agent, VERTEX_COUNT); + sim.setPopulationData(pop); + sim.step(); + sim.getPopulationData(pop); + // Check result matches + for (const auto& p : pop) { + EXPECT_EQ(p.getVariable("vertex_value"), 14 + static_cast(p.getVariable("tid"))); + } +} +FLAMEGPU_HOST_FUNCTION(hostfn_DeviceGetDefault_Vertex) { + auto graph = FLAMEGPU->environment.getDirectedGraph("graph"); + graph.setVertexCount(VERTEX_COUNT); +} +TEST(EnvironmentDirectedGraphTest, DeviceGetDefault_Vertex) { + ModelDescription model("test"); + auto& agent = model.newAgent("agent"); + agent.newVariable("vertex_value", 0u); + agent.newVariable("tid", 0); + agent.newFunction("DeviceGet_Vertex", DeviceGet_Vertex); + auto& graph = model.Environment().newDirectedGraph("graph"); + graph.newVertexProperty("vertex", 12); + model.newLayer().addHostFunction(hostfn_DeviceGetDefault_Vertex); + model.newLayer().addAgentFunction(DeviceGet_Vertex); + + CUDASimulation sim(model); + AgentVector pop(agent, VERTEX_COUNT); + sim.setPopulationData(pop); + sim.step(); + sim.getPopulationData(pop); + // Check result matches + for (const auto& p : pop) { + EXPECT_EQ(p.getVariable("vertex_value"), 12); + } +} +} // namespace flamegpu