From fb5428d520ed6e4d74d9cf4dec2fc9190637ba60 Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:33:35 +0200 Subject: [PATCH 1/7] removed warnings --- Algorithms/DepthFirstSearch.h | 2 +- Helpers/IO/ParserCSV.h | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Algorithms/DepthFirstSearch.h b/Algorithms/DepthFirstSearch.h index a685832..492f14b 100644 --- a/Algorithms/DepthFirstSearch.h +++ b/Algorithms/DepthFirstSearch.h @@ -117,7 +117,7 @@ class DepthFirstSearch { template struct SimpleOperation { - SimpleOperation(const GRAPH& graph, const OPERATION& operation) : graph(graph), operation(operation) {} + SimpleOperation(const GRAPH& graph, const OPERATION& operation) : operation(operation), graph(graph) {} inline void operator()(const Edge edge, const Vertex) {operation(graph.get(ToVertex, edge));} OPERATION operation; const GRAPH& graph; diff --git a/Helpers/IO/ParserCSV.h b/Helpers/IO/ParserCSV.h index c3feaa9..9941e50 100644 --- a/Helpers/IO/ParserCSV.h +++ b/Helpers/IO/ParserCSV.h @@ -178,7 +178,11 @@ class LineReader { } void setFileName(const char* fileName) { - strncpy(this->fileName, fileName, Error::MAX_FILE_NAME_LENGTH); +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" + std::strncpy(this->fileName, fileName, Error::MAX_FILE_NAME_LENGTH); +#pragma GCC diagnostic pop this->fileName[Error::MAX_FILE_NAME_LENGTH] = '\0'; } @@ -260,7 +264,11 @@ struct WithColumnName { WithColumnName() {std::memset(columnName, 0, MAX_COLUMN_NAME_LENGTH + 1);} void setColumnName(const char* columnName) { +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" std::strncpy(this->columnName, columnName, MAX_COLUMN_NAME_LENGTH); +#pragma GCC diagnostic pop this->columnName[MAX_COLUMN_NAME_LENGTH] = '\0'; } @@ -272,7 +280,11 @@ struct WithColumnContent { WithColumnContent() {std::memset(columnContent, 0, MAX_COLUMN_CONTENT_LENGTH + 1);} void setColumnContent(const char*columnContent) { +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" std::strncpy(this->columnContent, columnContent, MAX_COLUMN_CONTENT_LENGTH); +#pragma GCC diagnostic pop this->columnContent[MAX_COLUMN_CONTENT_LENGTH] = '\0'; } From 310cde54208fce7b8d5f76f6e357ef05278309df Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:34:05 +0200 Subject: [PATCH 2/7] graph serialize && correct clear & removeEdges --- DataStructures/Graph/Classes/DynamicGraph.h | 24 +++++++++++++++++++ DataStructures/Graph/Classes/EdgeList.h | 18 ++++++++++++++ DataStructures/Graph/Classes/StaticGraph.h | 26 +++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/DataStructures/Graph/Classes/DynamicGraph.h b/DataStructures/Graph/Classes/DynamicGraph.h index be7655f..3f50f0f 100644 --- a/DataStructures/Graph/Classes/DynamicGraph.h +++ b/DataStructures/Graph/Classes/DynamicGraph.h @@ -745,6 +745,30 @@ class DynamicGraphImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(vertexAttributes, edgeAttributes); + for (const Vertex vertex : vertices()) + edgeCount += outDegree(vertex); + Assert(satisfiesInvariants()); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, vertexAttributes, edgeAttributes); + for (const Vertex vertex : vertices()) + edgeCount += outDegree(vertex); + Assert(satisfiesInvariants()); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { vertexAttributes.serialize(fileName, separator); edgeAttributes.serialize(fileName, separator); diff --git a/DataStructures/Graph/Classes/EdgeList.h b/DataStructures/Graph/Classes/EdgeList.h index 0c0251e..01dd3b6 100644 --- a/DataStructures/Graph/Classes/EdgeList.h +++ b/DataStructures/Graph/Classes/EdgeList.h @@ -481,6 +481,24 @@ class EdgeListImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(vertexAttributes, edgeAttributes); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, vertexAttributes, edgeAttributes); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { vertexAttributes.serialize(fileName, separator); edgeAttributes.serialize(fileName, separator); diff --git a/DataStructures/Graph/Classes/StaticGraph.h b/DataStructures/Graph/Classes/StaticGraph.h index 4cbfc51..368e9b3 100644 --- a/DataStructures/Graph/Classes/StaticGraph.h +++ b/DataStructures/Graph/Classes/StaticGraph.h @@ -179,10 +179,16 @@ class StaticGraphImplementation { // Manipulation: inline void clear() noexcept { + beginOut.clear(); vertexAttributes.clear(); edgeAttributes.clear(); } + inline void removeEdges() noexcept { + std::fill(beginOut.begin(), beginOut.end(), Edge(0)); + edgeAttributes.clear(); + } + inline void reserve(const size_t numVertices, const size_t numEdges) noexcept { beginOut.reserve(numVertices + 1); vertexAttributes.reserve(numVertices); @@ -511,6 +517,26 @@ class StaticGraphImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(beginOut, vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(beginOut, vertexAttributes, edgeAttributes); + AssertMsg(satisfiesInvariants(), "Invariants not satisfied!"); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, beginOut, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, beginOut, vertexAttributes, edgeAttributes); + AssertMsg(satisfiesInvariants(), "Invariants not satisfied!"); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { IO::serialize(fileName + separator + "beginOut", beginOut); vertexAttributes.serialize(fileName, separator); From c5627a5052153a7a12f48c3ba8d47e7a2d56e507 Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:34:14 +0200 Subject: [PATCH 3/7] timestamp overflow --- Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h b/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h index 9e1331d..1d065e7 100644 --- a/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h +++ b/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h @@ -111,6 +111,12 @@ class StopEventGraphBuilder { inline void reduceTransfers(const TripId trip) noexcept { timestamp++; + + if (timestamp == 0) { + labels.clear(); + labels.resize(data.numberOfStops()); + } + const StopId* stops = data.stopArrayOfTrip(trip); for (StopIndex i = StopIndex(data.numberOfStopsInTrip(trip) - 1); i > 0; i--) { const int arrivalTime = data.getStopEvent(trip, i).arrivalTime; From 2b4b122694d345ef1f98c6ad6f0a95d99a6b177b Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:34:28 +0200 Subject: [PATCH 4/7] Export to CSV && graphml --- DataStructures/Graph/Utils/IO.h | 130 ++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 8 deletions(-) diff --git a/DataStructures/Graph/Utils/IO.h b/DataStructures/Graph/Utils/IO.h index 2de68e1..3c4d426 100644 --- a/DataStructures/Graph/Utils/IO.h +++ b/DataStructures/Graph/Utils/IO.h @@ -51,19 +51,133 @@ namespace Graph { toDimacs(fileBaseName, graph, graph.get(Weight)); } - template - inline void toGML(const std::string& fileBaseName, const GRAPH& graph) noexcept { - std::ofstream gml(fileBaseName + ".gml"); - Assert(gml, "Cannot create output stream for " << fileBaseName << ".gml"); - Assert(gml.is_open(), "Cannot open output stream for " << fileBaseName << ".gml"); + template + inline void toEdgeListCSV(const std::string& fileBaseName, const GRAPH& graph) noexcept + { + std::ofstream csv(fileBaseName + ".csv"); + AssertMsg(csv, "Cannot create output stream for " << fileBaseName << ".csv"); + AssertMsg(csv.is_open(), "Cannot open output stream for " << fileBaseName << ".csv"); + + csv << "FromVertex,ToVertex"; + + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + csv << ",TravelTime"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + csv << ",Distance"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + csv << ",ViaVertex"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + csv << ",Weight"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + csv << ",Capacity"; + if constexpr (GRAPH::HasEdgeAttribute(BundleSize)) + csv << ",BundleSize"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + csv << ",ReverseEdge"; + if constexpr (GRAPH::HasEdgeAttribute(EdgeFlags)) + csv << ",EdgeFlags"; + + csv << "\n"; + + for (const auto [edge, from] : graph.edgesWithFromVertex()) { + csv << size_t(from) << "," << size_t(graph.get(ToVertex, edge)); + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + csv << "," << (int)graph.get(TravelTime, edge); + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + csv << "," << (int)graph.get(Distance, edge); + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + csv << "," << size_t(graph.get(ViaVertex, edge)); + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + csv << "," << (int)graph.get(Weight, edge); + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + csv << "," << (int)graph.get(Capacity, edge); + if constexpr (GRAPH::HasEdgeAttribute(BundleSize)) + csv << "," << (int)graph.get(BundleSize, edge); + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + csv << "," << size_t(graph.get(ReverseEdge, edge)); + if constexpr (GRAPH::HasEdgeAttribute(EdgeFlags)) + csv << "," << join(graph.get(EdgeFlags, edge)); + csv << "\n"; + } + csv.close(); + } + + template + inline void toGML(const std::string& fileBaseName, const GRAPH& graph) noexcept + { + std::ofstream gml(fileBaseName + ".graphml"); + AssertMsg(gml, "Cannot create output stream for " << fileBaseName << ".graphml"); + AssertMsg(gml.is_open(), "Cannot open output stream for " << fileBaseName << ".graphml"); gml << "\n"; - gml << "\n"; + gml << "\n"; + if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { + gml << " \n"; + gml << " \n"; + } + if constexpr (GRAPH::HasVertexAttribute(Size)) + gml << " \n"; + if constexpr (GRAPH::HasVertexAttribute(Weight)) + gml << " \n"; + if constexpr (GRAPH::HasVertexAttribute(ViaVertex)) + gml << " \n"; + + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Size)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(BundleSize)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + gml << " \n"; gml << " \n"; + for (const Vertex vertex : graph.vertices()) { - gml << " \n"; + gml << " \n"; + + if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { + gml << " " << (float)graph.get(Coordinates, vertex).latitude << "\n"; + gml << " " << (float)graph.get(Coordinates, vertex).longitude << "\n"; + } + if constexpr (GRAPH::HasVertexAttribute(Size)) + gml << " " << (int)graph.get(Size, vertex) << "\n"; + if constexpr (GRAPH::HasVertexAttribute(Weight)) + gml << " " << (int)graph.get(Weight, vertex) << "\n"; + if constexpr (GRAPH::HasVertexAttribute(ViaVertex)) + gml << " " << (int)graph.get(ViaVertex, vertex) << "\n"; + + gml << " \n"; } for (const auto [edge, from] : graph.edgesWithFromVertex()) { - gml << " \n"; + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + gml << " " << (int)graph.get(TravelTime, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + gml << " " << (int)graph.get(Distance, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Size)) + gml << " " << (int)graph.get(Size, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(BundleSize)) + gml << " " << (int)graph.get(BundleSize, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + gml << " " << (int)graph.get(Weight, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + gml << " " << (int)graph.get(ReverseEdge, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + gml << " " << (int)graph.get(Capacity, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + gml << " " << size_t(graph.get(ViaVertex, edge)) << "\n"; + gml << " \n"; } gml << " \n"; gml << "" << std::endl; From 932e7f217cee71bb531c8a4bd9f0b56f921406f0 Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:34:40 +0200 Subject: [PATCH 5/7] added an example GTFS script --- Runnables/downloadExample.sh | 20 ++++++++++++++++++++ Runnables/exampleNetwork.script | 9 +++++++++ 2 files changed, 29 insertions(+) create mode 100644 Runnables/downloadExample.sh create mode 100644 Runnables/exampleNetwork.script diff --git a/Runnables/downloadExample.sh b/Runnables/downloadExample.sh new file mode 100644 index 0000000..713bd0f --- /dev/null +++ b/Runnables/downloadExample.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Define the target directory and URL +TARGET_DIR="../Datasets/Karlsruhe/GTFS" +ZIP_URL="https://projekte.kvv-efa.de/GTFS/google_transit.zip" +ZIP_FILE="$TARGET_DIR/google_transit.zip" + +# Create the target directory if it doesn't exist +mkdir -p $TARGET_DIR + +# Download the zip file +wget -O $ZIP_FILE $ZIP_URL + +# Extract the zip file into the target directory +unzip -o $ZIP_FILE -d $TARGET_DIR + +# Clean up the zip file +rm $ZIP_FILE + +echo "Download and extraction complete." \ No newline at end of file diff --git a/Runnables/exampleNetwork.script b/Runnables/exampleNetwork.script new file mode 100644 index 0000000..c854492 --- /dev/null +++ b/Runnables/exampleNetwork.script @@ -0,0 +1,9 @@ +parseGTFS ../Datasets/Karlsruhe/GTFS/ ../Datasets/Karlsruhe/GTFS/GTFS.binary +gtfsToIntermediate ../Datasets/Karlsruhe/GTFS/GTFS.binary 20240101 20240102 false false ../Datasets/Karlsruhe/intermediate.binary +reduceToMaximumConnectedComponent ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +reduceGraph ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +makeOneHopTransfers ../Datasets/Karlsruhe/intermediate.binary 86400 ../Datasets/Karlsruhe/intermediate.binary true +reduceToMaximumConnectedComponent ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +reduceGraph ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +intermediateToRAPTOR ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/raptor.binary +intermediateToCSA ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/csa.binary \ No newline at end of file From 51d6622a8ac5af4332506e6d98f175a29f38433f Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:48:58 +0200 Subject: [PATCH 6/7] added cmake option to use prefetching --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 592755c..1b002ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,13 @@ set(CMAKE_CXX_FLAGS "-pipe -march=native -Wfatal-errors") set(CMAKE_CXX_FLAGS_DEBUG "-rdynamic -Werror -Wpedantic -pedantic-errors -Wall -Wextra -Wparentheses -D_GLIBCXX_DEBUG -g -fno-omit-frame-pointer -O0") set(CMAKE_CXX_FLAGS_RELEASE "-ffast-math -DNDEBUG -O3") +# Add an option for enabling prefetch +option(USE_PREFETCH "Enable prefetch optimization" OFF) + +if(USE_PREFETCH) + add_compile_definitions(ENABLE_PREFETCH) +endif() + #Libraries set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) From fc26d7f12f5d5d460f546563b9a8ad8c5ea4be71 Mon Sep 17 00:00:00 2001 From: PatrickSteil Date: Sat, 24 Aug 2024 10:44:39 +0200 Subject: [PATCH 7/7] Prefetch && Prediction prefetch, but not for all algortihms, only a few prefetch CSA prefetch RAPTOR prefetch TB more work on csa even more csa Update TransitiveQuery.h --- Algorithms/CSA/CSA.h | 4 ++- Algorithms/CSA/DijkstraCSA.h | 2 +- Algorithms/CSA/HLCSA.h | 2 +- Algorithms/CSA/ULTRACSA.h | 2 +- Algorithms/RAPTOR/RAPTOR.h | 38 ++++++++++++++++++-- Algorithms/TripBased/Query/TransitiveQuery.h | 32 ++++++++++++++--- DataStructures/Graph/Classes/StaticGraph.h | 6 ++++ 7 files changed, 75 insertions(+), 11 deletions(-) diff --git a/Algorithms/CSA/CSA.h b/Algorithms/CSA/CSA.h index 2ab6b1b..b6b3b2a 100644 --- a/Algorithms/CSA/CSA.h +++ b/Algorithms/CSA/CSA.h @@ -133,7 +133,9 @@ class CSA { inline void scanConnections(const ConnectionId begin, const ConnectionId end) noexcept { for (ConnectionId i = begin; i < end; i++) { const Connection& connection = data.connections[i]; - if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) break; + + // This branch got mispredicted a lot! + if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) [[unlikely]] break; if (connectionIsReachable(connection, i)) { profiler.countMetric(METRIC_CONNECTIONS); arrivalByTrip(connection.arrivalStopId, connection.arrivalTime, connection.tripId); diff --git a/Algorithms/CSA/DijkstraCSA.h b/Algorithms/CSA/DijkstraCSA.h index 8a75778..598cf58 100644 --- a/Algorithms/CSA/DijkstraCSA.h +++ b/Algorithms/CSA/DijkstraCSA.h @@ -166,7 +166,7 @@ class DijkstraCSA { for (ConnectionId i = begin; i < end; i++) { const Connection& connection = data.connections[i]; runDijkstra(connection.departureTime); - if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) break; + if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) [[unlikely]] break; if (connectionIsReachable(connection, i)) { profiler.countMetric(METRIC_CONNECTIONS); arrivalByTrip(connection.arrivalStopId, connection.arrivalTime, connection.tripId); diff --git a/Algorithms/CSA/HLCSA.h b/Algorithms/CSA/HLCSA.h index 7af0a66..d4ffb76 100644 --- a/Algorithms/CSA/HLCSA.h +++ b/Algorithms/CSA/HLCSA.h @@ -142,7 +142,7 @@ class HLCSA { inline void scanConnections(const ConnectionId begin, const ConnectionId end) noexcept { for (ConnectionId i = begin; i < end; i++) { const Connection& connection = data.connections[i]; - if (targetVertex != noVertex && connection.departureTime > arrivalTime[targetVertex]) break; + if (targetVertex != noVertex && connection.departureTime > arrivalTime[targetVertex]) [[unlikely]] break; if (connectionIsReachable(connection, i)) { profiler.countMetric(METRIC_CONNECTIONS); arrivalByTrip(connection.arrivalStopId, connection.arrivalTime, connection.tripId); diff --git a/Algorithms/CSA/ULTRACSA.h b/Algorithms/CSA/ULTRACSA.h index 7024587..2053f93 100644 --- a/Algorithms/CSA/ULTRACSA.h +++ b/Algorithms/CSA/ULTRACSA.h @@ -152,7 +152,7 @@ class ULTRACSA { inline void scanConnections(const ConnectionId begin, const ConnectionId end) noexcept { for (ConnectionId i = begin; i < end; i++) { const Connection& connection = data.connections[i]; - if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) break; + if (targetStop != noStop && connection.departureTime > arrivalTime[targetStop]) [[unlikely]] break; if (connectionIsReachable(connection, i)) { profiler.countMetric(METRIC_CONNECTIONS); arrivalByTrip(connection.arrivalStopId, connection.arrivalTime, connection.tripId); diff --git a/Algorithms/RAPTOR/RAPTOR.h b/Algorithms/RAPTOR/RAPTOR.h index 221a5ce..0d6fad2 100644 --- a/Algorithms/RAPTOR/RAPTOR.h +++ b/Algorithms/RAPTOR/RAPTOR.h @@ -220,7 +220,17 @@ class RAPTOR { } inline void collectRoutesServingUpdatedStops() noexcept { - for (const StopId stop : stopsUpdatedByTransfer) { + auto& valuesToLoopOver = stopsUpdatedByTransfer.getValues(); + for (size_t i = 0; i < valuesToLoopOver.size(); ++i) { + + #ifdef ENABLE_PREFETCH + if (i + 4 < valuesToLoopOver.size()) { + __builtin_prefetch(&(previousRound()[valuesToLoopOver[i + 4]])); + __builtin_prefetch(&(data.routeSegments[data.firstRouteSegmentOfStop[valuesToLoopOver[i + 4]]])); + } + #endif + + const StopId stop = valuesToLoopOver[i]; Assert(data.isStop(stop), "Stop " << stop << " is out of range!"); const int arrivalTime = previousRound()[stop].arrivalTime; Assert(arrivalTime < never, "Updated stop has arrival time = never!"); @@ -240,7 +250,19 @@ class RAPTOR { inline void scanRoutes() noexcept { stopsUpdatedByRoute.clear(); - for (const RouteId route : routesServingUpdatedStops.getKeys()) { + auto& valuesToLoopOver = routesServingUpdatedStops.getKeys(); + + for (size_t i = 0; i < valuesToLoopOver.size(); ++i) { + + #ifdef ENABLE_PREFETCH + if (i + 4 < valuesToLoopOver.size()) { + __builtin_prefetch(data.stopArrayOfRoute(valuesToLoopOver[i + 4])); + __builtin_prefetch(data.firstTripOfRoute(valuesToLoopOver[i + 4])); + __builtin_prefetch(data.lastTripOfRoute(valuesToLoopOver[i + 4])); + } + #endif + + const RouteId route = valuesToLoopOver[i]; profiler.countMetric(METRIC_ROUTES); StopIndex stopIndex = routesServingUpdatedStops[route]; const size_t tripSize = data.numberOfStopsInRoute(route); @@ -276,7 +298,17 @@ class RAPTOR { inline void relaxTransfers() noexcept { stopsUpdatedByTransfer.clear(); routesServingUpdatedStops.clear(); - for (const StopId stop : stopsUpdatedByRoute) { + + auto& valuesToLoopOver = stopsUpdatedByRoute.getValues(); + for (size_t i = 0; i < valuesToLoopOver.size(); ++i) { + + #ifdef ENABLE_PREFETCH + if (i + 4 < valuesToLoopOver.size()) { + __builtin_prefetch(SeparateRouteAndTransferEntries ? &previousRound()[valuesToLoopOver[i + 4]].arrivalTime : ¤tRound()[valuesToLoopOver[i + 4]].arrivalTime); + data.transferGraph.prefetchBeginOut(valuesToLoopOver[i + 4]); + } + #endif + const int earliestArrivalTime = SeparateRouteAndTransferEntries ? previousRound()[stop].arrivalTime : currentRound()[stop].arrivalTime; for (const Edge edge : data.transferGraph.edgesFrom(stop)) { if constexpr (INITIAL_TRANSFERS && PreventDirectWalking) { diff --git a/Algorithms/TripBased/Query/TransitiveQuery.h b/Algorithms/TripBased/Query/TransitiveQuery.h index 08b420c..5d35016 100644 --- a/Algorithms/TripBased/Query/TransitiveQuery.h +++ b/Algorithms/TripBased/Query/TransitiveQuery.h @@ -198,7 +198,17 @@ class TransitiveQuery { } } reachedRoutes.sort(); - for (const RouteId route : reachedRoutes) { + auto& valuesToLoopOver = reachedRoutes.getValues(); + + for (size_t i = 0; i < valuesToLoopOver.size(); ++i) { + #ifdef ENABLE_PREFETCH + if (i + 4 < valuesToLoopOver.size()) { + __builtin_prefetch(&(routeLabels[valuesToLoopOver[i + 4]])); + __builtin_prefetch(&(data.firstTripOfRoute[valuesToLoopOver[i + 4]])); + } + #endif + + const RouteId route = valuesToLoopOver[i]; const RouteLabel& label = routeLabels[route]; const StopIndex endIndex = label.end(); const TripId firstTrip = data.firstTripOfRoute[route]; @@ -225,17 +235,31 @@ class TransitiveQuery { targetLabels.emplace_back(targetLabels.back()); // Evaluate final transfers in order to check if the target is reachable for (size_t i = roundBegin; i < roundEnd; i++) { + #ifdef ENABLE_PREFETCH + if (i + 4 < roundEnd) { + __builtin_prefetch(&(queue[i + 4])); + __builtin_prefetch(&(data.arrivalEvents[queue[i + 4].begin])); + } + #endif + const TripLabel& label = queue[i]; profiler.countMetric(METRIC_SCANNED_TRIPS); for (StopEventId j = label.begin; j < label.end; j++) { profiler.countMetric(METRIC_SCANNED_STOPS); - if (data.arrivalEvents[j].arrivalTime >= minArrivalTime) break; + if (data.arrivalEvents[j].arrivalTime >= minArrivalTime) [[unlikely]] break; const int timeToTarget = transferToTarget[data.arrivalEvents[j].stop]; if (timeToTarget != INFTY) addTargetLabel(data.arrivalEvents[j].arrivalTime + timeToTarget, i); } } // Find the range of transfers for each trip for (size_t i = roundBegin; i < roundEnd; i++) { + #ifdef ENABLE_PREFETCH + if (i + 4 < roundEnd) { + __builtin_prefetch(&(queue[i + 4])); + __builtin_prefetch(&(data.arrivalEvents[queue[i + 4].begin])); + } + #endif + TripLabel& label = queue[i]; for (StopEventId j = label.begin; j < label.end; j++) { if (data.arrivalEvents[j].arrivalTime >= minArrivalTime) label.end = j; @@ -270,7 +294,7 @@ class TransitiveQuery { inline void enqueue(const Edge edge, const size_t parent) noexcept { profiler.countMetric(METRIC_ENQUEUES); const EdgeLabel& label = edgeLabels[edge]; - if (reachedIndex.alreadyReached(label.trip, label.stopEvent - label.firstEvent)) return; + if (reachedIndex.alreadyReached(label.trip, label.stopEvent - label.firstEvent)) [[likely]] return; queue[queueSize] = TripLabel(label.stopEvent, StopEventId(label.firstEvent + reachedIndex(label.trip)), parent); queueSize++; Assert(queueSize <= queue.size(), "Queue is overfull!"); @@ -373,4 +397,4 @@ class TransitiveQuery { Profiler profiler; }; -} +} \ No newline at end of file diff --git a/DataStructures/Graph/Classes/StaticGraph.h b/DataStructures/Graph/Classes/StaticGraph.h index 368e9b3..62ed6db 100644 --- a/DataStructures/Graph/Classes/StaticGraph.h +++ b/DataStructures/Graph/Classes/StaticGraph.h @@ -775,6 +775,12 @@ class StaticGraphImplementation { return true; } + inline void prefetchBeginOut(const Vertex vertex) const noexcept { + AssertMsg(isVertex(vertex), "Vertex is not valid!"); + + __builtin_prefetch(&beginOut[vertex]); + } + private: std::vector beginOut; VertexAttributes vertexAttributes;