[m-rev.] diff: Provide access to runtime granularity control primitives.

Paul Bone pbone at csse.unimelb.edu.au
Thu Jun 4 16:45:58 AEST 2009


Estimated hours taken: 10 
Branches: main

Provide access to runtime granularity control primitives.

In 2007 Zoltan implemented some runtime granularity control primitives in the
runtime system.  This change provides access to them from procedures in the
par_builtin module, this is useful for testing.  Recording of parallelization
decisions has also been implemented to help verify and debug this approach.
The variables that the runtime granularity control method depends upon have
been made volatile.

The runtime granularity control method is:
	 NumCPUs > (executable contexts + sparks on global queue).

I previously thought that this was incorrect but instead my testing code was
broken, having fixed it this works correctly.

library/par_builtin.m:
    Define a procedure as above so that it can be called explicits from code,
		this is useful for testing.

runtime/mercury_context.c:
runtime/mercury_context.h:
	  Make the variables used by the granularity control method volatile.
		Provide debugging code enabled by a C macro.

Index: library/par_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/par_builtin.m,v
retrieving revision 1.15
diff -u -p -b -r1.15 par_builtin.m
--- library/par_builtin.m	22 Apr 2009 03:03:16 -0000	1.15
+++ library/par_builtin.m	4 Jun 2009 06:31:45 -0000
@@ -25,6 +25,8 @@
 :- module par_builtin.
 :- interface.
 
+:- import_module io.
+
 :- type future(T).
 
     % Allocate a new future object.  A future acts as an intermediary for a
@@ -53,11 +55,32 @@
     %
 :- impure pred signal(future(T)::in, T::in) is det.
 
+    % These predicates are intended to be used as conditions to decide if
+    % something should be done in parallel or sequence.  They are true when
+    % they beleive parallel execution is optimisitc and false otherwise.
+    %
+    % They can either be used by compiler transformations or directly in user
+    % code - which is useful for testing.
+    %
+
     % A hook for the compiler's granularity transformation to hang
-    % an arbitrary test on.
+    % an arbitrary test on.  This predicate does not have a definition, it is
+    % simply used as a hook by the compiler.
     %
 :- impure pred evaluate_parallelism_condition is semidet.
 
+    % par_cond_outstanding_jobs_vs_num_cpus(NumCPUs)
+    %
+    % True iff NumCPUs > executable contexts + global sparks.
+    %
+    % Consider passing MR_num_threads as the argument.
+    %
+:- impure pred par_cond_outstanding_jobs_vs_num_cpus(int::in) is semidet.
+
+    % Close the file that was used to log the parallel condition decisions.
+    %
+:- pred par_cond_close_stats_file(io::di, io::uo) is det.
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -344,5 +367,38 @@ INIT mercury_sys_init_par_builtin_module
     MR_fatal_error(""evaluate_parallelism_condition called"");
 ").
 
+:- pragma foreign_proc("C",
+    par_cond_outstanding_jobs_vs_num_cpus(NumCPUs::in),
+    [will_not_call_mercury, thread_safe, may_not_duplicate],
+"
+#ifdef MR_LL_PARALLEL_CONJ
+    SUCCESS_INDICATOR = MR_choose_parallel_over_sequential_cond(NumCPUs);
+ #ifdef MR_DEBUG_RUNTIME_GRANULARITY_CONTROL
+    MR_record_conditional_parallelism_descision(SUCCESS_INDICATOR);
+ #endif
+#else
+    MR_fatal_error(
+      ""par_cond_outstanding_jobs_vs_num_cpus is unavailable in this grade"");
+#endif
+").
+
+:- pragma foreign_proc("C",
+    par_cond_close_stats_file(IO0::di, IO::uo),
+    [will_not_call_mercury, thread_safe, may_not_duplicate, promise_pure],
+    "
+#ifdef MR_LL_PARALLEL_CONJ
+ #ifdef MR_DEBUG_RUNTIME_GRANULARITY_CONTROL
+    MR_write_out_conditional_parallelism_log();
+ #else
+    MR_fatal_error(
+      ""par_cond_close_stats_file is unavailable in this build"");
+ #endif
+#else
+    MR_fatal_error(
+      ""par_cond_close_stats_file is unavailable in this grade"");
+#endif
+    IO = IO0; 
+    ").
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.60
diff -u -p -b -r1.60 mercury_context.c
--- runtime/mercury_context.c	19 Mar 2008 05:30:00 -0000	1.60
+++ runtime/mercury_context.c	4 Jun 2009 06:27:28 -0000
@@ -79,8 +79,10 @@ static MR_Context       *free_small_cont
 #endif
 
 #ifdef  MR_LL_PARALLEL_CONJ
-int MR_num_idle_engines = 0;
-int MR_num_outstanding_contexts_and_sparks = 0;
+int volatile MR_num_idle_engines = 0;
+int volatile MR_num_outstanding_contexts_and_sparks = 0;
+
+static MercuryLock MR_par_cond_stats_lock;
 #endif
 
 /*---------------------------------------------------------------------------*/
@@ -98,6 +100,9 @@ MR_init_thread_stuff(void)
   #ifdef MR_LL_PARALLEL_CONJ
     MR_init_wsdeque(&MR_spark_queue, MR_INITIAL_GLOBAL_SPARK_QUEUE_SIZE);
     pthread_mutex_init(&MR_sync_term_lock, MR_MUTEX_ATTR);
+  #ifdef MR_DEBUG_RUNTIME_GRANULARITY_CONTROL
+    pthread_mutex_init(&MR_par_cond_stats_lock, MR_MUTEX_ATTR);
+  #endif
   #endif
     pthread_mutex_init(&MR_STM_lock, MR_MUTEX_ATTR);
   #ifndef MR_THREAD_LOCAL_STORAGE
@@ -681,6 +686,61 @@ MR_END_MODULE
 
 #endif /* !MR_HIGHLEVEL_CODE */
 
+#ifdef MR_LL_PARALLEL_CONJ
+
+/*
+ * Debugging functions for runtime granularity control.
+ */
+
+#ifdef MR_DEBUG_RUNTIME_GRANULARITY_CONTROL
+
+#define MR_PAR_COND_STATS_FILENAME "par_cond_stats.log"
+static FILE * volatile MR_par_cond_stats_file = NULL;
+static volatile MR_Unsigned MR_par_cond_stats_last;
+static volatile MR_Unsigned MR_par_cond_stats_last_count;
+
+void MR_record_conditional_parallelism_descision(MR_Unsigned descision)
+{
+    MR_LOCK(&MR_par_cond_stats_lock, "record_conditional_parallelism_decision");
+    if (MR_par_cond_stats_file == NULL)
+    {
+        MR_par_cond_stats_file = fopen(MR_PAR_COND_STATS_FILENAME, "w");
+        MR_par_cond_stats_last = descision;
+        MR_par_cond_stats_last_count = 1;
+    }
+    else
+    {
+        if (descision == MR_par_cond_stats_last)
+        {
+            MR_par_cond_stats_last_count++;
+        }
+        else
+        {
+            fprintf(MR_par_cond_stats_file, "%d %d\n", MR_par_cond_stats_last,
+                MR_par_cond_stats_last_count);
+            MR_par_cond_stats_last = descision;
+            MR_par_cond_stats_last_count = 1;
+        }
+    }
+    MR_UNLOCK(&MR_par_cond_stats_lock, "record_conditional_parallelism_decision i");
+}
+
+void MR_write_out_conditional_parallelism_log(void)
+{
+    MR_LOCK(&MR_par_cond_stats_lock, "write_out_conditional_parallelism_log");
+    if (MR_par_cond_stats_file != NULL)
+    {
+        fprintf(MR_par_cond_stats_file, "%d %d\n", MR_par_cond_stats_last,
+            MR_par_cond_stats_last_count);
+        fclose(MR_par_cond_stats_file);
+        MR_par_cond_stats_file = NULL;
+    }
+    MR_UNLOCK(&MR_par_cond_stats_lock, "write_out_conditional_parallelism_log i");
+}
+
+#endif /* MR_DEBUG_RUNTIME_GRANULARITY_CONTROL */
+#endif /* MR_LL_PARALLEL_CONJ */
+
 /* forward decls to suppress gcc warnings */
 void mercury_sys_init_scheduler_wrapper_init(void);
 void mercury_sys_init_scheduler_wrapper_init_type_tables(void);
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.46
diff -u -p -b -r1.46 mercury_context.h
--- runtime/mercury_context.h	5 Sep 2008 11:19:33 -0000	1.46
+++ runtime/mercury_context.h	4 Jun 2009 06:31:09 -0000
@@ -388,7 +388,7 @@ extern  MR_PendingContext   *MR_pending_
   ** XXX We may need to use atomic instructions or memory fences on some
   ** architectures.
   */
-  extern    int     MR_num_idle_engines;
+  extern volatile int   MR_num_idle_engines;
 
   /*
   ** The number of contexts that are not in the free list (i.e. are executing
@@ -406,7 +406,7 @@ extern  MR_PendingContext   *MR_pending_
   ** scanned.  (Getting the garbage collector not to scan contexts on the free
   ** list should be possible though.)
   */
-  extern    int     MR_num_outstanding_contexts_and_sparks;
+  extern volatile int   MR_num_outstanding_contexts_and_sparks;
 #endif  /* !MR_LL_PARALLEL_CONJ */
 
 /*---------------------------------------------------------------------------*/
@@ -874,6 +874,29 @@ extern  void        MR_schedule_context(
   /* This needs to come after the definition of MR_SparkDeque_Struct. */
   #include "mercury_wsdeque.h"
 
-#endif /* not MR_LL_PARALLEL_CONJ */
+#ifdef MR_DEBUG_RUNTIME_GRANULARITY_CONTROL
+
+  /*
+  ** These functions can be used to debug the runtime granularity control
+  ** methods implemented above.
+  */
+
+  /*
+  ** decision is 1 if we choose to parallelise something and 0 if code should
+  ** be run sequentially.
+  ** This is not (yet) thread safe.
+  */
+  void MR_record_conditional_parallelism_descision(MR_Unsigned descision);
+
+  /*
+  ** flush and close the log of conditional parallelism decisions 
+  ** This is not thread safe.
+  ** This is a no-op if no parallelism decisions have been recorded.
+  */
+  void MR_write_out_conditional_parallelism_log(void);
+
+#endif /* MR_DEBUG_RUNTIME_GRANULARITY_CONTROL */
+
+#endif /* MR_LL_PARALLEL_CONJ */
 
 #endif /* not MERCURY_CONTEXT_H */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20090604/81218a76/attachment.sig>


More information about the reviews mailing list