[m-rev.] for review: Add thread.num_processors/3
Paul Bone
paul at bone.id.au
Tue May 10 16:23:13 AEST 2016
For review by anyone. This is actually pretty simple, but people may wish
to review the name of the new predicate.
---
Add thread.num_processors/3
Add a predicate that retrieves the number of processors available to this
process if known.
library/thread.m:
As above.
runtime/mercury_context.c:
The existing code that determines the number of processors was only used
on thread safe low-level C grades. Make it also available for thread
safe high-level C grades.
Add a fall back (less accurate) method of determining the number of
processors.
Remove an out-of-date comment.
runtime/mercury_context.h:
Export the number of available processors.
scripts/ml.in:
Link to libhwloc (if configured) on thread safe high and low-level C
grades.
NEWS:
Announce new predicate.
configure.ac:
Update a --help message.
---
NEWS | 3 +++
configure.ac | 3 +--
library/thread.m | 55 +++++++++++++++++++++++++++++++++++++++++++++++
runtime/mercury_context.c | 31 ++++++++++++++------------
runtime/mercury_context.h | 5 +++++
scripts/ml.in | 6 +++---
6 files changed, 84 insertions(+), 19 deletions(-)
diff --git a/NEWS b/NEWS
index 9b9f8a5..b1a6648 100644
--- a/NEWS
+++ b/NEWS
@@ -152,6 +152,9 @@ Changes to the Mercury standard library:
* We have added thread.spawn_native/4 to dedicate an OS thread to a Mercury
thread. thread.spawn/4 was added as well.
+* We have added thread.num_processors/3 which returns the number of
+ processors available for parallel work.
+
+ We have deprecated the impure init/1 function in thread.semaphore.
* In C grades, the math module now provides the fused multiply-add operation
diff --git a/configure.ac b/configure.ac
index 9619319..3a2258b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5160,8 +5160,7 @@ PKG_PROG_PKG_CONFIG
AC_ARG_WITH([hwloc],
[AS_HELP_STRING([--without-hwloc],
- [Do not use libhwloc to detect the processors available in low-level C
- parallel grades.])],
+ [Do not use libhwloc to detect the processors available.])],
[],
[with_hwloc=check])
diff --git a/library/thread.m b/library/thread.m
index 0177681..9f1e96f 100644
--- a/library/thread.m
+++ b/library/thread.m
@@ -93,6 +93,21 @@
%
:- pred yield(io::di, io::uo) is det.
+ % num_processors(Num, !IO)
+ %
+ % Retrieve the number of processors available to this process for
+ % parallel execution, if known.
+ %
+ % Note that the number of available processors can be different from the
+ % actual number of processors/cores:
+ %
+ % + It includes hardware threads.
+ % + The Mercury grade may restrict the process to one processor.
+ % + The OS may be configured to restrict the number of processors
+ % available (e.g. cpuset(7) on Linux).
+ %
+:- pred num_processors(maybe(int)::out, io::di, io::uo) is det.
+
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
@@ -709,5 +724,45 @@ public static class RunGoal implements Runnable {
}").
%---------------------------------------------------------------------------%
+
+num_processors(MaybeProcs, !IO) :-
+ num_processors(Procs, Success, !IO),
+ (
+ Success = yes,
+ MaybeProcs = yes(Procs)
+ ;
+ Success = no,
+ MaybeProcs = no
+ ).
+
+:- pred num_processors(int::out, bool::out, io::di, io::uo) is det.
+
+:- pragma foreign_proc("C",
+ num_processors(Procs::out, Success::out, _IO0::di, _IO::uo),
+ [promise_pure, thread_safe, will_not_call_mercury,
+ will_not_throw_exception, tabled_for_io],
+"
+#ifdef MR_THREAD_SAFE
+ Procs = MR_num_processors;
+ Success = MR_YES;
+#else
+ Procs = 1;
+ Success = MR_YES;
+#endif
+").
+
+:- pragma foreign_proc("Java",
+ num_processors(Procs::out, Success::out, _IO0::di, _IO::uo),
+ [promise_pure, thread_safe, will_not_call_mercury,
+ will_not_throw_exception, tabled_for_io],
+"
+ Procs = Runtime.getRuntime().availableProcessors();
+ Success = bool.YES;
+").
+
+% On other backends se don't know how to determine this yet.
+num_processors(0, no, !IO).
+
+%---------------------------------------------------------------------------%
:- end_module thread.
%---------------------------------------------------------------------------%
diff --git a/runtime/mercury_context.c b/runtime/mercury_context.c
index 49dfcd2..3b225d8 100644
--- a/runtime/mercury_context.c
+++ b/runtime/mercury_context.c
@@ -59,7 +59,7 @@ ENDINIT
#include "mercury_windows.h"
#endif
-#if defined(MR_LL_PARALLEL_CONJ) && defined(MR_HAVE_HWLOC)
+#if defined(MR_THREAD_SAFE) && defined(MR_HAVE_HWLOC)
#include <hwloc.h>
#endif
@@ -212,19 +212,18 @@ static MR_Integer MR_profile_parallel_regular_context_kept = 0;
#endif /* ! MR_HIGHLEVEL_CODE */
#endif /* MR_PROFILE_PARALLEL_EXECUTION_SUPPORT */
+#ifdef MR_THREAD_SAFE
/*
** Detect number of processors.
*/
-#ifdef MR_LL_PARALLEL_CONJ
-static unsigned MR_num_processors;
- #if defined(MR_HAVE_HWLOC)
+unsigned MR_num_processors;
+#if defined(MR_HAVE_HWLOC)
static hwloc_topology_t MR_hw_topology;
static hwloc_cpuset_t MR_hw_available_pus = NULL;
- #elif defined(MR_HAVE_SCHED_SETAFFINITY)
+#elif defined(MR_HAVE_SCHED_SETAFFINITY)
static cpu_set_t *MR_available_cpus;
/* The number of CPUs that MR_available_cpus can refer to */
static unsigned MR_cpuset_size = 0;
- #endif
#endif
/*
@@ -236,6 +235,7 @@ static MercuryLock MR_thread_pinning_lock;
static unsigned MR_num_threads_left_to_pin;
MR_Unsigned MR_primordial_thread_cpu;
#endif
+#endif
#if defined(MR_LL_PARALLEL_CONJ) && \
defined(MR_PROFILE_PARALLEL_EXECUTION_SUPPORT)
@@ -283,7 +283,7 @@ MR_SparkDeque **MR_spark_deques = NULL;
/*---------------------------------------------------------------------------*/
-#ifdef MR_LL_PARALLEL_CONJ
+#ifdef MR_THREAD_SAFE
/*
** Reset or initialize the cpuset that tracks which CPUs are available for
** binding.
@@ -294,6 +294,7 @@ MR_reset_available_cpus(void);
static void
MR_detect_num_processors(void);
+#ifdef MR_LL_PARALLEL_CONJ
static void
MR_setup_num_threads(void);
@@ -322,6 +323,7 @@ static MR_bool
try_notify_engine(MR_EngineId engine_id, int action,
union MR_engine_wake_action_data *action_data, MR_Unsigned engine_state);
#endif
+#endif
#ifdef MR_PROFILE_PARALLEL_EXECUTION_SUPPORT
/*
@@ -382,10 +384,10 @@ MR_init_context_stuff(void)
MR_KEY_CREATE(&MR_backjump_next_choice_id_key, (void *)0);
#endif
- #ifdef MR_LL_PARALLEL_CONJ
MR_detect_num_processors();
assert(MR_num_processors > 0);
+ #ifdef MR_LL_PARALLEL_CONJ
MR_setup_num_threads();
assert(MR_num_ws_engines > 0);
@@ -419,11 +421,11 @@ MR_init_context_stuff(void)
#endif /* MR_THREAD_SAFE */
}
+#ifdef MR_THREAD_SAFE
/*
** Detect number of processors
*/
-#ifdef MR_LL_PARALLEL_CONJ
static void
MR_reset_available_cpus(void)
{
@@ -478,7 +480,9 @@ MR_reset_available_cpus(void)
if (-1 == sched_getaffinity(0, cpuset_size, MR_available_cpus)) {
MR_perror("Couldn't get CPU affinity");
+ #if defined(MR_LL_PARALLEL_CONJ) && defined(MR_HAVE_THREAD_PINNING)
MR_thread_pinning = MR_FALSE;
+ #endif
CPU_FREE(MR_available_cpus);
MR_available_cpus = NULL;
}
@@ -504,11 +508,6 @@ MR_detect_num_processors(void)
#ifdef MR_HAVE_HWLOC
MR_num_processors = hwloc_bitmap_weight(MR_hw_available_pus);
#elif defined(MR_HAVE_SCHED_GETAFFINITY)
- /*
- ** This looks redundant but its not. MR_num_processors is a guess that was
- ** gathered by using sysconf. But the number of CPUs in the CPU_SET is the
- ** actual number of CPUs that this process is restricted to.
- */
MR_num_processors = CPU_COUNT_S(MR_cpuset_size, MR_available_cpus);
#elif defined(MR_WIN32_GETSYSTEMINFO)
{
@@ -516,12 +515,15 @@ MR_detect_num_processors(void)
GetSystemInfo(&sysinfo);
MR_num_processors = sysinfo.dwNumberOfProcessors;
}
+ #elif defined(MR_HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
+ MR_num_processors = sysconf(_SC_NPROCESSORS_ONLN);
#else
#warning "Cannot detect MR_num_processors"
MR_num_processors = 1;
#endif
}
+#ifdef MR_LL_PARALLEL_CONJ
static void
MR_setup_num_threads(void)
{
@@ -542,6 +544,7 @@ MR_setup_num_threads(void)
#endif
}
#endif /* MR_LL_PARALLEL_CONJ */
+#endif /* MR_THREAD_SAFE */
/*
** Thread pinning
diff --git a/runtime/mercury_context.h b/runtime/mercury_context.h
index 5503b54..1f5f0ae 100644
--- a/runtime/mercury_context.h
+++ b/runtime/mercury_context.h
@@ -390,6 +390,11 @@ extern MR_bool MR_profile_parallel_execution;
extern MR_Stats MR_profile_parallel_executed_local_sparks;
#endif
+#ifdef MR_THREAD_SAFE
+/* The number of processors available */
+extern unsigned MR_num_processors;
+#endif
+
/*
** As well as the runqueue, we maintain a linked list of contexts
** and associated file descriptors that are suspended blocked for
diff --git a/scripts/ml.in b/scripts/ml.in
index 52103be..03e496a 100644
--- a/scripts/ml.in
+++ b/scripts/ml.in
@@ -387,11 +387,11 @@ case $use_thread_libs.$make_shared_lib in
THREAD_LIBS=""
;;
esac
-case "$thread_safe,$highlevel_code,$all_libs" in
- true,false,static)
+case "$thread_safe,$all_libs" in
+ true,static)
THREAD_LIBS="$THREAD_LIBS $HWLOC_STATIC_LIBS"
;;
- true,false,shared)
+ true,shared)
THREAD_LIBS="$THREAD_LIBS $HWLOC_LIBS"
;;
esac
--
2.8.1
More information about the reviews
mailing list