Skip to content

Commit 1b09d4f

Browse files
committed
Existing directed graph tests still pass, iteration should work needs tests.
1 parent 3fb5b6c commit 1b09d4f

File tree

4 files changed

+110
-53
lines changed

4 files changed

+110
-53
lines changed

include/flamegpu/runtime/environment/HostEnvironmentDirectedGraph.cuh

+5-30
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class HostEnvironmentDirectedGraph {
212212
class Edge {
213213
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
214214
const cudaStream_t stream;
215-
id_t source_vertex_id, destination_vertex_id;
215+
unsigned int edge_index;
216216
friend Edge EdgeMap::operator[](SrcDestPair);
217217
friend struct Iterator;
218218

@@ -289,30 +289,21 @@ class HostEnvironmentDirectedGraph {
289289
Iterator(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, difference_type _index)
290290
: directed_graph(std::move(_directed_graph))
291291
, stream(_stream)
292-
, index(_index)
293292
, edge(_directed_graph, _stream, _index) {}
294293
reference operator*() const { return edge; }
295294
pointer operator->() const { return &edge; }
296-
Iterator& operator++() { index++; update_edge(); return *this; }
297-
Iterator operator++(int) { Iterator tmp = *this; ++(*this); tmp.update_edge(); return tmp; }
295+
Iterator& operator++() { edge.edge_index++; return *this; }
296+
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
298297

299-
bool operator== (const Iterator& a, const Iterator& b) const { return a.index == b.index; }
300-
bool operator!= (const Iterator& a, const Iterator& b) const { return a.index != b.index; }
298+
bool operator== (const Iterator& other) const { return edge.edge_index == other.edge.edge_index; }
299+
bool operator!= (const Iterator& other) const { return edge.edge_index != other.edge.edge_index; }
301300

302301
Iterator begin() { return { directed_graph, stream, 0 }; }
303302
Iterator end() { return { directed_graph, stream, directed_graph->getEdgeCount() }; }
304303

305304
private:
306-
void update_edge() {
307-
edge.source_vertex_id = directed_graph->getSourceVertexID(index, stream);
308-
edge.destination_vertex_id = directed_graph->getDestinationVertexID(index, stream);
309-
if (edge.source_vertex_id == ID_NOT_SET || edge.destination_vertex_id == ID_NOT_SET) {
310-
index = directed_graph->getEdgeCount();
311-
}
312-
}
313305
std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> directed_graph;
314306
cudaStream_t stream;
315-
difference_type index;
316307
mutable Edge edge;
317308
};
318309

@@ -343,8 +334,6 @@ std::vector<T> HostEnvironmentDirectedGraph::VertexMap::Vertex::getPropertyArray
343334
}
344335
template<typename T>
345336
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setPropertyArray(const std::string& property_name, const std::vector<T>& property_value) const {
346-
// Get index
347-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
348337
size_type n = property_value.size();
349338
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, n, stream);
350339
if (!property_value.size()) {
@@ -355,8 +344,6 @@ void HostEnvironmentDirectedGraph::EdgeMap::Edge::setPropertyArray(const std::st
355344
}
356345
template<typename T>
357346
std::vector<T> HostEnvironmentDirectedGraph::EdgeMap::Edge::getPropertyArray(const std::string& property_name) const {
358-
// Get index
359-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
360347
return directed_graph->getEdgePropertyArray<T>(property_name, edge_index, stream);
361348
}
362349
#endif
@@ -422,16 +409,12 @@ std::array<T, N> HostEnvironmentDirectedGraph::VertexMap::Vertex::getProperty(co
422409

423410
template<typename T>
424411
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const T property_value) {
425-
// Get index
426-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
427412
size_type element_ct = 1;
428413
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
429414
val[edge_index] = property_value;
430415
}
431416
template<typename T, flamegpu::size_type N>
432417
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const size_type element_index, const T property_value) {
433-
// Get index
434-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
435418
size_type element_ct = N;
436419
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
437420
if (element_index >= element_ct) {
@@ -442,25 +425,19 @@ void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string&
442425
}
443426
template<typename T, flamegpu::size_type N>
444427
void HostEnvironmentDirectedGraph::EdgeMap::Edge::setProperty(const std::string& property_name, const std::array<T, N>& property_value) {
445-
// Get index
446-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
447428
size_type element_ct = N;
448429
T* val = directed_graph->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
449430
std::array<T, N>* val2 = reinterpret_cast<std::array<T, N>*>(val);
450431
val2[edge_index] = property_value;
451432
}
452433
template<typename T>
453434
T HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name) const {
454-
// Get index
455-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
456435
size_type element_ct = 1;
457436
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
458437
return rtn[edge_index];
459438
}
460439
template<typename T, flamegpu::size_type N>
461440
T HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name, const size_type element_index) const {
462-
// Get index
463-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
464441
size_type element_ct = N;
465442
const T* rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
466443
if (element_index >= element_ct) {
@@ -471,8 +448,6 @@ T HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& pr
471448
}
472449
template<typename T, flamegpu::size_type N>
473450
std::array<T, N> HostEnvironmentDirectedGraph::EdgeMap::Edge::getProperty(const std::string& property_name) const {
474-
// Get index
475-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
476451
size_type element_ct = N;
477452
const T *rtn = const_cast<const detail::CUDAEnvironmentDirectedGraphBuffers*>(directed_graph.get())->getEdgePropertyBuffer<T>(property_name, element_ct, stream);
478453
const std::array<T, N>* rtn2 = reinterpret_cast<const std::array<T, N>*>(rtn);

include/flamegpu/simulation/detail/CUDAEnvironmentDirectedGraphBuffers.cuh

+21-1
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,30 @@ class CUDAEnvironmentDirectedGraphBuffers {
265265
* @param src_vertex_id The ID that has been assigned to the source vertex of the edge
266266
* @param dest_vertex_id The ID that has been assigned to the destination vertex of the edge
267267
*
268-
* @throws exception::IDCollision If the ID is already assigned to a different vertex
268+
* @throws exception::IDCollision If the ID source/dest pair is already assigned to a different edge
269269
*/
270270
void setEdgeSourceDestination(unsigned int edge_index, id_t src_vertex_id, id_t dest_vertex_id);
271271
/**
272+
* Updates the edge ID buffer
273+
* Updates the internal host map of src:dest->index
274+
*
275+
* @param edge_index The index of the edge
276+
* @param src_vertex_id The ID that has been assigned to the source vertex of the edge
277+
*
278+
* @throws exception::IDCollision If the ID source/dest pair is already assigned to a different edge
279+
*/
280+
void setEdgeSource(unsigned int edge_index, id_t src_vertex_id);
281+
/**
282+
* Updates the edge ID buffer
283+
* Updates the internal host map of src:dest->index
284+
*
285+
* @param edge_index The index of the edge
286+
* @param dest_vertex_id The ID that has been assigned to the destination vertex of the edge
287+
*
288+
* @throws exception::IDCollision If the ID source/dest pair is already assigned to a different edge
289+
*/
290+
void setEdgeDestination(unsigned int edge_index, id_t dest_vertex_id);
291+
/**
272292
* Returns the index of the edge with the given source and destination vertices
273293
* @param src_vertex_id The ID that has been assigned to the source vertex of the edge
274294
* @param dest_vertex_id The ID that has been assigned to the destination vertex of the edge

src/flamegpu/runtime/environment/HostEnvironmentDirectedGraph.cu

+5-19
Original file line numberDiff line numberDiff line change
@@ -152,38 +152,24 @@ Edge EdgeMap::operator[](SrcDestPair source_dest_vertex_ids) {
152152
Edge::Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, id_t _source_vertex_id, id_t _dest_vertex_id)
153153
: directed_graph(std::move(_directed_graph))
154154
, stream(_stream)
155-
, source_vertex_id(_source_vertex_id)
156-
, destination_vertex_id(_dest_vertex_id) { }
155+
, edge_index(directed_graph->getEdgeIndex(_source_vertex_id, _dest_vertex_id)) { }
157156

158-
Edge::Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, unsigned int edge_index)
157+
Edge::Edge(std::shared_ptr<detail::CUDAEnvironmentDirectedGraphBuffers> _directed_graph, const cudaStream_t _stream, unsigned int _edge_index)
159158
: directed_graph(std::move(_directed_graph))
160159
, stream(_stream)
161-
, source_vertex_id(_directed_graph->getSourceVertexID(edge_index, _stream))
162-
, destination_vertex_id(_directed_graph->getDestinationVertexID(edge_index, _stream))
160+
, edge_index(_edge_index)
163161
{ }
164162
void Edge::setSourceVertexID(id_t _source_vertex_id) {
165-
// Get index
166-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
167163
// Update ID
168-
directed_graph->setEdgeSourceDestination(edge_index, _source_vertex_id, destination_vertex_id);
169-
// Update local copy of ID
170-
source_vertex_id = _source_vertex_id;
164+
directed_graph->setEdgeSource(edge_index, _source_vertex_id);
171165
}
172166
void Edge::setDestinationVertexID(id_t _dest_vertex_id) {
173-
// Get index
174-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
175167
// Update ID
176-
directed_graph->setEdgeSourceDestination(edge_index, source_vertex_id, _dest_vertex_id);
177-
// Update local copy of ID
178-
destination_vertex_id = _dest_vertex_id;
168+
directed_graph->setEdgeDestination(edge_index, _dest_vertex_id);
179169
}
180170
void Edge::setSourceDestinationVertexID(id_t _source_vertex_id, id_t _dest_vertex_id) {
181-
// Get index
182-
const unsigned int edge_index = directed_graph->getEdgeIndex(source_vertex_id, destination_vertex_id);
183171
// Update ID
184172
directed_graph->setEdgeSourceDestination(edge_index, _source_vertex_id, _dest_vertex_id);
185-
// Update local copy of ID
186-
destination_vertex_id = _dest_vertex_id;
187173
}
188174
id_t Edge::getSourceVertexID() const {
189175
return getProperty<id_t, 2>(GRAPH_SOURCE_DEST_VARIABLE_NAME, 1);

src/flamegpu/simulation/detail/CUDAEnvironmentDirectedGraphBuffers.cu

+79-3
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,17 @@ void CUDAEnvironmentDirectedGraphBuffers::syncDevice_async(detail::CUDAScatter&
411411
}
412412
}
413413
if (requires_rebuild && vertex_count && edge_count) {
414+
if (edge_count != h_edge_index_map.size()) {
415+
THROW exception::IDNotSet("Unable to build graph, only %u/%u edges have been assigned both a source and destination, in CUDAEnvironmentDirectedGraphBuffers::syncDevice_async()", edge_count, static_cast<unsigned int>(h_edge_index_map.size()));
416+
} else if (vertex_count != h_vertex_index_map.size()) {
417+
THROW exception::IDNotSet("Unable to build graph, only %u/%u vertices have been assigned an ID, in CUDAEnvironmentDirectedGraphBuffers::syncDevice_async()", vertex_count, static_cast<unsigned int>(h_vertex_index_map.size()));
418+
}
414419
// Construct the vertex ID : index map
415420
{
416421
if (vertex_id_min == std::numeric_limits<unsigned int>::max() || vertex_id_max == std::numeric_limits<unsigned int>::min()) {
417422
THROW flamegpu::exception::IDOutOfBounds("No IDs have been set, in CUDAEnvironmentDirectedGraphBuffers::syncDevice_async()");
418423
}
419424
const unsigned int ID_RANGE = 1 + vertex_id_max - vertex_id_min;
420-
if (ID_RANGE < vertex_count) {
421-
THROW flamegpu::exception::IDNotSet("Not all vertices have been assigned a unique ID, in CUDAEnvironmentDirectedGraphBuffers::syncDevice_async()");
422-
}
423425
if (d_vertex_index_map) {
424426
gpuErrchk(flamegpu::detail::cuda::cudaFree(d_vertex_index_map));
425427
}
@@ -688,6 +690,80 @@ void CUDAEnvironmentDirectedGraphBuffers::setEdgeSourceDestination(unsigned int
688690
// Require rebuild before use
689691
markForRebuild();
690692
}
693+
void CUDAEnvironmentDirectedGraphBuffers::setEdgeSource(unsigned int edge_index, id_t src_vertex_id) {
694+
if (edge_index >= edge_count) {
695+
THROW exception::OutOfBoundsException("Edge index exceeds bounds %u >= %u, "
696+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeSource()\n", edge_index, edge_count);
697+
} else if (src_vertex_id == ID_NOT_SET) {
698+
THROW exception::IDOutOfBounds("Source vertex ID of %u is not valid, "
699+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeSource()\n", ID_NOT_SET);
700+
}
701+
// Purge old edge src/dest from host map
702+
auto& eb = edge_buffers.at(GRAPH_SOURCE_DEST_VARIABLE_NAME);
703+
// Don't need to update buffer, src_dest is not stored as ID on device
704+
id_t& edge_dest = static_cast<id_t*>(eb.h_ptr)[edge_index * 2 + 0];
705+
id_t& edge_src = static_cast<id_t*>(eb.h_ptr)[edge_index * 2 + 1];
706+
707+
// Remove old edge from src map if it's complete
708+
if (edge_src != ID_NOT_SET && edge_dest != ID_NOT_SET) {
709+
h_edge_index_map.erase({edge_src, edge_dest});
710+
}
711+
712+
// Update edge's src dest in buffer
713+
edge_src = src_vertex_id;
714+
eb.ready = Buffer::Host;
715+
716+
// Add new edge ID to host map if it's complete
717+
if (edge_src != ID_NOT_SET && edge_dest != ID_NOT_SET) {
718+
// validate it's not already in use
719+
const auto find = h_edge_index_map.find({ edge_src, edge_dest });
720+
if (find != h_edge_index_map.end()) {
721+
THROW exception::IDCollision("Edge collision, an edge has already been assigned source %u dest %u at index %u, "
722+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeSource()\n", src_vertex_id, edge_dest, find->second);
723+
}
724+
h_edge_index_map.emplace(std::pair{src_vertex_id, edge_dest }, edge_index);
725+
}
726+
727+
// Require rebuild before use
728+
markForRebuild();
729+
}
730+
void CUDAEnvironmentDirectedGraphBuffers::setEdgeDestination(unsigned int edge_index, id_t dest_vertex_id) {
731+
if (edge_index >= edge_count) {
732+
THROW exception::OutOfBoundsException("Edge index exceeds bounds %u >= %u, "
733+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeDestination()\n", edge_index, edge_count);
734+
} else if (dest_vertex_id == ID_NOT_SET) {
735+
THROW exception::IDOutOfBounds("Destination vertex ID of %u is not valid, "
736+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeDestination()\n", ID_NOT_SET);
737+
}
738+
// Purge old edge src/dest from host map
739+
auto& eb = edge_buffers.at(GRAPH_SOURCE_DEST_VARIABLE_NAME);
740+
// Don't need to update buffer, src_dest is not stored as ID on device
741+
id_t& edge_dest = static_cast<id_t*>(eb.h_ptr)[edge_index * 2 + 0];
742+
id_t& edge_src = static_cast<id_t*>(eb.h_ptr)[edge_index * 2 + 1];
743+
744+
// Update edge's src dest in buffer
745+
if (edge_src != ID_NOT_SET && edge_dest != ID_NOT_SET) {
746+
h_edge_index_map.erase({edge_src, edge_dest});
747+
}
748+
749+
// Update edge's src dest in buffer
750+
edge_dest = dest_vertex_id;
751+
eb.ready = Buffer::Host;
752+
753+
// Add new edge ID to host map if it's complete
754+
if (edge_src != ID_NOT_SET && edge_dest != ID_NOT_SET) {
755+
// validate it's not already in use
756+
const auto find = h_edge_index_map.find({ edge_src, edge_dest });
757+
if (find != h_edge_index_map.end()) {
758+
THROW exception::IDCollision("Edge collision, an edge has already been assigned source %u dest %u at index %u, "
759+
"in CUDAEnvironmentDirectedGraphBuffers::setEdgeDestination()\n", edge_src, edge_dest, find->second);
760+
}
761+
h_edge_index_map.emplace(std::pair{ edge_src, edge_dest }, edge_index);
762+
}
763+
764+
// Require rebuild before use
765+
markForRebuild();
766+
}
691767
unsigned int CUDAEnvironmentDirectedGraphBuffers::getEdgeIndex(id_t src_vertex_id, id_t dest_vertex_id) const {
692768
const auto find = h_edge_index_map.find({src_vertex_id, dest_vertex_id});
693769
if (find == h_edge_index_map.end()) {

0 commit comments

Comments
 (0)