Commit 1277a9d4 authored by Tiago Peixoto's avatar Tiago Peixoto

Switch default OpenMP schedule to 'runtime'

This also implements direct manipulation of OpenMP settings (schedule
and number of threads) via python.
parent d6899abe
......@@ -24,6 +24,7 @@ libgraph_tool_core_la_SOURCES = \
graph_copy.cc \
graph_filtering.cc \
graph_io.cc \
graph_openmp.cc \
graph_properties.cc \
graph_properties_copy.cc \
graph_properties_group.cc \
......
......@@ -45,7 +45,7 @@ void normalize_betweenness(const Graph& g,
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -68,7 +68,7 @@ struct get_closeness
get_vertex_dists_t get_vertex_dists;
size_t HN = HardNumVertices()(g);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
vertex_t v = vertex(i, g);
......
......@@ -49,7 +49,7 @@ struct get_eigentrust
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -73,7 +73,7 @@ struct get_eigentrust
c_sum.reserve(num_vertices(g));
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -91,7 +91,7 @@ struct get_eigentrust
// init inferred trust t
int i, N = num_vertices(g), V = HardNumVertices()(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -106,7 +106,7 @@ struct get_eigentrust
{
delta = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:delta)
schedule(runtime) if (N > 100) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -138,7 +138,7 @@ struct get_eigentrust
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -59,7 +59,7 @@ struct get_eigenvector
{
norm = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:norm)
schedule(runtime) if (N > 100) reduction(+:norm)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -85,7 +85,7 @@ struct get_eigenvector
delta = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:delta)
schedule(runtime) if (N > 100) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -105,7 +105,7 @@ struct get_eigenvector
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -55,7 +55,7 @@ struct get_hits
// init centrality
int i, N = num_vertices(g), V = HardNumVertices()(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -73,7 +73,7 @@ struct get_hits
{
x_norm = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:x_norm)
schedule(runtime) if (N > 100) reduction(+:x_norm)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -108,7 +108,7 @@ struct get_hits
delta = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:delta)
schedule(runtime) if (N > 100) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -130,7 +130,7 @@ struct get_hits
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -57,7 +57,7 @@ struct get_katz
while (delta >= epsilon)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -81,7 +81,7 @@ struct get_katz
delta = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:delta)
schedule(runtime) if (N > 100) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -100,7 +100,7 @@ struct get_katz
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -43,7 +43,7 @@ struct get_pagerank
// init degs
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -62,7 +62,7 @@ struct get_pagerank
{
delta = 0;
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:delta)
schedule(runtime) if (N > 100) reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......@@ -96,7 +96,7 @@ struct get_pagerank
if (iter % 2 != 0)
{
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -106,7 +106,7 @@ struct get_trust_transitivity
property_traits<InferredTrustMap>::value_type::value_type t_type;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
vertex_t v = vertex(i, g);
......@@ -116,7 +116,7 @@ struct get_trust_transitivity
}
N = (target == -1) ? num_vertices(g) : target + 1;
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = (target == -1) ? 0 : target; i < N; ++i)
{
vertex_t tgt = vertex(i, g);
......@@ -210,7 +210,7 @@ struct get_trust_transitivity
distance_zero(t_type(1)));
#pragma omp parallel for default(shared) private(j) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (j = 0; j < N2; ++j)
{
vertex_t src = vertex(j, g);
......@@ -224,7 +224,7 @@ struct get_trust_transitivity
}
#pragma omp parallel for default(shared) private(j) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (j = 0; j < N2; ++j)
{
vertex_t src = vertex(j, g);
......
......@@ -107,7 +107,7 @@ struct get_global_clustering
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i,temp) \
schedule(static) if (N > 100) reduction(+:triangles, n)
schedule(runtime) if (N > 100) reduction(+:triangles, n)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -125,7 +125,7 @@ struct get_global_clustering
double cerr = 0.0;
#pragma omp parallel for default(shared) private(i,temp) \
schedule(static) if (N > 100) reduction(+:cerr)
schedule(runtime) if (N > 100) reduction(+:cerr)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -151,7 +151,7 @@ struct set_clustering_to_property
typename get_undirected_graph<Graph>::type ug(g);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -121,7 +121,7 @@ struct get_extended_clustering
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
vertex_t v = vertex(i, g);
......
......@@ -357,7 +357,7 @@ struct get_all_motifs
int i, N = (p < 1) ? V.size() : num_vertices(g);
#pragma omp parallel for default(shared) private(i, sig) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
std::vector<std::vector<typename graph_traits<Graph>::vertex_descriptor> >
......
......@@ -108,7 +108,7 @@ struct get_communities
// sample a new spin for every vertex
int NV = num_vertices(g),i;
#pragma omp parallel for default(shared) private(i)\
reduction(+:E) schedule(static) if (NV > 100)
reduction(+:E) schedule(runtime) if (NV > 100)
for (i = 0; i < NV; ++i)
{
vertex_t v = vertex(i, g);
......@@ -211,7 +211,7 @@ struct get_communities
{
int NV = num_vertices(g), i;
#pragma omp parallel for default(shared) private(i)\
schedule(static) if (NV > 100)
schedule(runtime) if (NV > 100)
for (i = 0; i < NV; ++i)
{
vertex_t v = vertex(i, g);
......@@ -380,7 +380,7 @@ public:
void Update(size_t k, size_t old_s, size_t s)
{
int i, NK = _degs.size();
#pragma omp parallel for default(shared) private(i) schedule(static) if (NK > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (NK > 100)
for (i = 0; i < NK; ++i)
{
size_t k1 = _degs[i], k2 = k;
......@@ -406,7 +406,7 @@ public:
_Nks[k].erase(old_s);
_Nks[k][s]++;
#pragma omp parallel for default(shared) private(i) schedule(static) if (NK > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (NK > 100)
for (i = 0; i < NK; ++i)
{
size_t k1 = _degs[i], k2 = k;
......
......@@ -52,7 +52,7 @@ struct get_assortativity_coefficient
SharedMap<map_t> sa(a), sb(b);
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) firstprivate(sa,sb)\
schedule(static) if (N > 100) reduction(+:e_kk, n_edges)
schedule(runtime) if (N > 100) reduction(+:e_kk, n_edges)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -86,7 +86,7 @@ struct get_assortativity_coefficient
// "jackknife" variance
double err = 0.0;
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)\
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)\
reduction(+:err)
for (i = 0; i < N; ++i)
{
......@@ -131,7 +131,7 @@ struct get_scalar_assortativity_coefficient
double a = 0.0, b = 0.0, da = 0.0, db = 0.0;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100) reduction(+:e_xy,n_edges,a,b,da,db)
schedule(runtime) if (N > 100) reduction(+:e_xy,n_edges,a,b,da,db)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......@@ -167,7 +167,7 @@ struct get_scalar_assortativity_coefficient
r_err = 0.0;
double err = 0.0;
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)\
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)\
reduction(+:err)
for (i = 0; i < N; ++i)
{
......
......@@ -67,7 +67,7 @@ struct get_avg_correlation
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
firstprivate(s_sum, s_sum2, s_count) schedule(static) if (N > 100)
firstprivate(s_sum, s_sum2, s_count) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -60,7 +60,7 @@ struct get_correlation_histogram
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
firstprivate(s_hist) schedule(static) if (N > 100)
firstprivate(s_hist) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......
......@@ -135,7 +135,7 @@ struct get_geometric
int i;
#pragma omp parallel for default(shared) private(i, box) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -71,7 +71,7 @@ struct get_lattice
vector<int> pos(shape.size());
//#pragma omp parallel for default(shared) private(i)
// firstprivate(pos) schedule(static) if (N > 100)
// firstprivate(pos) schedule(runtime) if (N > 100)
for (int i = 0; i < N; ++i)
{
get_pos(i, shape, pos);
......
......@@ -628,7 +628,7 @@ inline void remove_vertex(Vertex v, adj_list<Vertex>& g)
int i, N = g._out_edges.size();
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
auto& oes = g._out_edges[i];
......
......@@ -60,6 +60,7 @@ struct LibInfo
}
};
template <class ValueType>
struct vector_from_list
{
......@@ -373,15 +374,6 @@ string get_graph_type(GraphInterface& g)
return name;
}
bool openmp_enabled()
{
#ifdef USING_OPENMP
return true;
#else
return false;
#endif
}
// numpy array interface weirdness
void* do_import_array()
{
......@@ -401,6 +393,8 @@ void mark_edges(GraphInterface& gi, boost::any prop);
void export_python_interface();
void export_openmp();
BOOST_PYTHON_MODULE(libgraph_tool_core)
{
using namespace boost::python;
......@@ -426,7 +420,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
.def("empty", &boost::any::empty);
def("graph_filtering_enabled", &graph_filtering_enabled);
def("openmp_enabled", &openmp_enabled);
export_openmp();
boost::mpl::for_each<boost::mpl::push_back<scalar_types,string>::type>(export_vector_types());
......
......@@ -123,7 +123,7 @@ struct copy_vertex_property_dispatch
ptgt->get_unchecked(num_vertices(tgt));
int i, N = num_vertices(src);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<GraphSrc>::vertex_descriptor v = vertex(i, src);
......@@ -197,7 +197,7 @@ struct copy_edge_property_dispatch
ptgt->get_unchecked(num_edges(tgt));
int i, N = num_vertices(src);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<GraphSrc>::vertex_descriptor v = vertex(i, src);
......
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2014 Tiago de Paula Peixoto <tiago@skewed.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph.hh"
#include <boost/python.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
// OpenMP control
#ifdef USING_OPENMP
#include <omp.h>
#endif
bool openmp_enabled()
{
#ifdef USING_OPENMP
return true;
#else
return false;
#endif
}
size_t openmp_get_num_threads()
{
#ifdef USING_OPENMP
return omp_get_max_threads();
#else
throw GraphException("OpenMP was not enabled during compilation")
#endif
}
void openmp_set_num_threads(int n)
{
#ifdef USING_OPENMP
omp_set_num_threads(n);
#else
throw GraphException("OpenMP was not enabled during compilation")
#endif
}
python::tuple openmp_get_schedule()
{
#ifdef USING_OPENMP
omp_sched_t kind;
int chunk;
omp_get_schedule(&kind, &chunk);
string skind;
switch (kind)
{
case omp_sched_static:
skind = "static";
break;
case omp_sched_dynamic:
skind = "dynamic";
break;
case omp_sched_guided:
skind = "guided";
break;
case omp_sched_auto:
skind = "auto";
break;
default:
throw GraphException("Unknown schedule type");
}
return python::make_tuple(skind, chunk);
#else
throw GraphException("OpenMP was not enabled during compilation")
#endif
}
void openmp_set_schedule(string skind, int chunk)
{
#ifdef USING_OPENMP
omp_sched_t kind;
if (skind == "static")
kind = omp_sched_static;
else if (skind == "dynamic")
kind = omp_sched_dynamic;
else if (skind == "guided")
kind = omp_sched_guided;
else if (skind == "auto")
kind = omp_sched_auto;
else
throw GraphException("Unknown schedule type: " + skind);
omp_set_schedule(kind, chunk);
#else
throw GraphException("OpenMP was not enabled during compilation")
#endif
}
void export_openmp()
{
using namespace boost::python;
def("openmp_enabled", &openmp_enabled);
def("openmp_get_num_threads", &openmp_get_num_threads);
def("openmp_set_num_threads", &openmp_set_num_threads);
def("openmp_get_schedule", &openmp_get_schedule);
def("openmp_set_schedule", &openmp_set_schedule);
};
......@@ -264,7 +264,7 @@ struct do_mark_edges
{
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) \
schedule(static) if (N > 100)
schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -242,7 +242,7 @@ struct get_degree_map
typename map_t::unchecked_t deg_map = cdeg_map.get_unchecked(num_vertices(g));
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
......
......@@ -255,7 +255,7 @@ struct do_sanitize_pos
void operator()(Graph& g, PosMap pos) const
{
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i) schedule(static) if (N > 100)
#pragma omp parallel for default(shared) private(i) schedule(runtime) if (N > 100)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
......