cpchung
cpchung

Reputation: 844

How to setup cmake to link parallel boost-graph?

I am trying to set up CMake such that boost-graph is properly linked. But I am running into an error when doing

find_package(Boost REQUIRED COMPONENTS graph mpi) # finding mpi is a problem
-- Found boost_mpi 1.77.0 at ~/miniconda3/envs/xyz/lib/cmake/boost_mpi-1.77.0
--   Library has no variants and is considered not found
CMake Error at /home/tom/miniconda3/envs/pokeai/lib/cmake/Boost-1.77.0/BoostConfig.cmake:141 (find_package):
  Found package configuration file:

    ~/miniconda3/envs/xyz/lib/cmake/boost_mpi-1.77.0/boost_mpi-config.cmake

  but it set boost_mpi_FOUND to FALSE so package "boost_mpi" is considered to
  be NOT FOUND.  Reason given by package:

  No suitable build variant has been found.

I have tried to find a doc from Boost-graph for this but it seems like the cmake part is not there for the setup. A line from boost_mpi-config.cmake looks suspicious to me and it is related to the error.

To produce the problem locally, you might find the files below useful.

CMakeLists.txt used:

cmake_minimum_required(VERSION 3.23)

set(Boost_VERBOSE ON)
message(CHECK_START "Looking for MPI")
find_package(MPI REQUIRED COMPONENTS CXX C)

#find_package(Boost REQUIRED COMPONENTS graph)
find_package(Boost REQUIRED COMPONENTS graph mpi) # finding mpi is a problem
add_executable(parallel_boost_graph parallel_boost_graph.cpp)

target_link_libraries(parallel_boost_graph
        PUBLIC
        MPI::MPI_CXX
        ${Boost_LIBRARIES}
        Boost::graph
        #        Boost::mpi
        )

A small example code to reproduce the problem:

// Enable PBGL interfaces to BGL algorithms
#include <boost/graph/use_mpi.hpp>

// Communication via MPI
#include <boost/graph/distributed/mpi_process_group.hpp>

// Dijkstra's single-source shortest paths algorithm
#include <boost/graph/dijkstra_shortest_paths.hpp>

// Distributed adjacency list
#include <boost/graph/distributed/adjacency_list.hpp>

// METIS Input
#include <boost/graph/metis.hpp>

// Graphviz Output
#include <boost/graph/distributed/graphviz.hpp>

// Standard Library includes
#include <fstream>
#include <string>

#ifdef BOOST_NO_EXCEPTIONS
void boost::throw_exception(std::exception const& ex) {
  std::cout << ex.what() << std::endl;
  abort();
}
#endif

using namespace boost;
using boost::graph::distributed::mpi_process_group;

/* An undirected, weighted graph with distance values stored on the
vertices. */
typedef adjacency_list<vecS, distributedS<mpi_process_group, vecS>, undirectedS,
                       /*Vertex properties=*/property<vertex_distance_t, float>,
                       /*Edge properties=*/property<edge_weight_t, float> >
    Graph;

using namespace boost;
using boost::graph::distributed::mpi_process_group;

int main(int argc, char* argv[]) {
  boost::mpi::environment env(argc, argv);

  typedef adjacency_list<listS, distributedS<mpi_process_group, vecS>,
                         directedS,
                         no_property,                  // Vertex properties
                         property<edge_weight_t, int>  // Edge properties
                         >
      graph_t;
  typedef graph_traits<graph_t>::vertex_descriptor vertex_descriptor;
  typedef graph_traits<graph_t>::edge_descriptor edge_descriptor;

  typedef std::pair<int, int> Edge;
  const int num_nodes = 5;
  enum nodes { A, B, C, D, E };
  char name[] = "ABCDE";
  Edge edge_array[] = {Edge(A, C), Edge(B, B), Edge(B, D),
                       Edge(B, E), Edge(C, B), Edge(C, D),
                       Edge(D, E), Edge(E, A), Edge(E, B)};
  int weights[] = {1, 2, 1, 2, 7, 3, 1, 1, 1};
  int num_arcs = sizeof(edge_array) / sizeof(Edge);

  graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes);
  // Keeps track of the predecessor of each vertex
  std::vector<vertex_descriptor> p(num_vertices(g));
  // Keeps track of the distance to each vertex
  std::vector<int> d(num_vertices(g));

  vertex_descriptor s = vertex(A, g);
  dijkstra_shortest_paths(g, s,
                          predecessor_map(make_iterator_property_map(
                                              p.begin(), get(vertex_index, g)))
                              .distance_map(make_iterator_property_map(
                                  d.begin(), get(vertex_index, g))));

  std::cout << std::endl;

  return EXIT_SUCCESS;
}

For your convenience, you can also check out this repo to reproduce the problem: https://bitbucket.org/cpchung/debugging-only

Upvotes: 1

Views: 426

Answers (1)

Flamefire
Flamefire

Reputation: 5807

The parallel Boost.Graph library needs Boost.MPI. The CMake find process (or better: the Boost.MPI CMake config files) tell you

No suitable build variant has been found.

This happens when there are no libboost_mpi-variant-*.cmake files next to boost_mpi-config.cmake which is the case when there was an error in packaging (e.g. however copied the files to the final destination missed those) or the Boost.MPI library simply was not build. I suspect the latter.

So what you need to do is either get a Boost installation containing Boost.MPI via whatever package manager you use which could be as simple as installing a single additional package in case the Boost libraries were split into individual packages. Or you can build & install Boost from source yourself making sure the b2 command can find the MPI headers and hence Boost.MPI is build.

Note: Using the CMake variables Boost_DEBUG and Boost_VERBOSE (set them via cmake -DBoost_DEBUG=ON) can help in finding why a library was not found or rejected.

Upvotes: 1

Related Questions