Browse Source

gcc: Document implicit task CPU implementations.

* doc/chapters/basic-examples.texi (Hello World using the C Extension,
  Vector Scaling Using the C Extension): Use implicit CPU task
  implementations.

* doc/chapters/c-extensions.texi (Defining Tasks): Augment documentation
  of `task' with implicit CPU task implementation definitions.  Add a
  version of the example that uses an implicit CPU task implementation.
  (Conditional Extensions): Update to use an implicit CPU task
  implementation.  Update description.
Ludovic Courtès 13 years ago
parent
commit
41d87dd4e9
2 changed files with 95 additions and 43 deletions
  1. 4 14
      doc/chapters/basic-examples.texi
  2. 91 29
      doc/chapters/c-extensions.texi

+ 4 - 14
doc/chapters/basic-examples.texi

@@ -71,12 +71,8 @@ has a single implementation for CPU:
 /* Task declaration.  */
 static void my_task (int x) __attribute__ ((task));
 
-/* Declaration of the CPU implementation of `my_task'.  */
-static void my_task_cpu (int x)
-   __attribute__ ((task_implementation ("cpu", my_task)));
-
-/* Definition of said CPU implementation.  */
-static void my_task_cpu (int x)
+/* Definition of the CPU implementation of `my_task'.  */
+static void my_task (int x)
 @{
   printf ("Hello, world!  With x = %d\n", x);
 @}
@@ -331,19 +327,13 @@ has to be defined:
 @cartouche
 @smallexample
 /* Declare the `vector_scal' task.  */
-
 static void vector_scal (unsigned size, float vector[size],
                          float factor)
   __attribute__ ((task));
 
-/* Declare and define the standard CPU implementation.  */
-
-static void vector_scal_cpu (unsigned size, float vector[size],
-                             float factor)
-  __attribute__ ((task_implementation ("cpu", vector_scal)));
-
+/* Define the standard CPU implementation.  */
 static void
-vector_scal_cpu (unsigned size, float vector[size], float factor)
+vector_scal (unsigned size, float vector[size], float factor)
 @{
   unsigned i;
   for (i = 0; i < size; i++)

+ 91 - 29
doc/chapters/c-extensions.texi

@@ -87,8 +87,11 @@ The following function attributes are provided:
 @item task
 @cindex @code{task} attribute
 Declare the given function as a StarPU task.  Its return type must be
-@code{void}, and it must not be defined---instead, a definition will
-automatically be provided by the compiler.
+@code{void}.  When a function declared as @code{task} has a user-defined
+body, that body is interpreted as the @dfn{implicit definition of the
+task's CPU implementation} (see example below).  In all cases, the
+actual definition of a task's body is automatically generated by the
+compiler.
 
 Under the hood, declaring a task leads to the declaration of the
 corresponding @code{codelet} (@pxref{Codelet and Tasks}).  If one or
@@ -157,6 +160,44 @@ A @code{matmult} task is defined; it has only one implementation,
 @var{B} are input buffers, whereas @var{C} is considered an input/output
 buffer.
 
+@cindex implicit task CPU implementation
+For convenience, when a function declared with the @code{task} attribute
+has a user-defined body, that body is assumed to be that of the CPU
+implementation of a task, which we call an @dfn{implicit task CPU
+implementation}.  Thus, the above snippet can be simplified like this:
+
+@cartouche
+@smallexample
+#define __output  __attribute__ ((output))
+
+static void matmul (const float *A, const float *B,
+                    __output float *C,
+                    unsigned nx, unsigned ny, unsigned nz)
+  __attribute__ ((task));
+
+/* Implicit definition of the CPU implementation of the
+   `matmul' task.  */
+static void
+matmul (const float *A, const float *B, __output float *C,
+        unsigned nx, unsigned ny, unsigned nz)
+@{
+  unsigned i, j, k;
+
+  for (j = 0; j < ny; j++)
+    for (i = 0; i < nx; i++)
+      @{
+        for (k = 0; k < nz; k++)
+          C[j * nx + i] += A[j * nz + k] * B[k * nx + i];
+      @}
+@}
+@end smallexample
+@end cartouche
+
+@noindent
+Use of implicit CPU task implementations as above has the advantage that
+the code is valid sequential code when StarPU's GCC plug-in is not used
+(@pxref{Conditional Extensions}).
+
 CUDA and OpenCL implementations can be declared in a similar way:
 
 @cartouche
@@ -349,36 +390,37 @@ The code below illustrates how to define a task and its implementations
 in a way that allows it to be compiled without the GCC plug-in:
 
 @smallexample
-/* The macros below abstract over the attributes specific to
-   StarPU-GCC and the name of the CPU implementation.  */
-#ifdef STARPU_GCC_PLUGIN
-# define __task  __attribute__ ((task))
-# define CPU_TASK_IMPL(task)  task ## _cpu
-#else
-# define __task
-# define CPU_TASK_IMPL(task)  task
-#endif
+/* This program is valid, whether or not StarPU's GCC plug-in
+   is being used.  */
 
 #include <stdlib.h>
 
-static void matmul (const float *A, const float *B, float *C,
-                    unsigned nx, unsigned ny, unsigned nz) __task;
-
-#ifdef STARPU_GCC_PLUGIN
+/* The attribute below is ignored when GCC is not used.  */
+static void matmul (const float *A, const float *B, float * C,
+                    unsigned nx, unsigned ny, unsigned nz)
+  __attribute__ ((task));
 
-static void matmul_cpu (const float *A, const float *B, float *C,
-                        unsigned nx, unsigned ny, unsigned nz)
-  __attribute__ ((task_implementation ("cpu", matmul)));
+static void
+matmul (const float *A, const float *B, float * C,
+        unsigned nx, unsigned ny, unsigned nz)
+@{
+  /* Code of the CPU kernel here...  */
+@}
 
-#endif
+#ifdef STARPU_GCC_PLUGIN
+/* Optional OpenCL task implementation.  */
 
+static void matmul_opencl (const float *A, const float *B, float * C,
+                           unsigned nx, unsigned ny, unsigned nz)
+  __attribute__ ((task_implementation ("opencl", matmul)));
 
 static void
-CPU_TASK_IMPL (matmul) (const float *A, const float *B, float *C,
-                        unsigned nx, unsigned ny, unsigned nz)
+matmul_opencl (const float *A, const float *B, float * C,
+               unsigned nx, unsigned ny, unsigned nz)
 @{
-  /* Code of the CPU kernel here...  */
+  /* Code that invokes the OpenCL kernel here...  */
 @}
+#endif
 
 int
 main (int argc, char *argv[])
@@ -395,7 +437,7 @@ main (int argc, char *argv[])
 
   /* When StarPU-GCC is used, the call below is asynchronous;
      otherwise, it is synchronous.  */
-  matmul (A, B, C, 123, 42, 7);
+  matmul ((float *) A, (float *) B, (float *) C, 123, 42, 7);
 
 #pragma starpu wait
 #pragma starpu shutdown
@@ -404,12 +446,32 @@ main (int argc, char *argv[])
 @}
 @end smallexample
 
-Note that attributes such as @code{task} are simply ignored by GCC when
-the StarPU plug-in is not loaded, so the @code{__task} macro could be
-omitted altogether.  However, @command{gcc -Wall} emits a warning for
-unknown attributes, which can be inconvenient, and other compilers may
-be unable to parse the attribute syntax.  Thus, using macros such as
-@code{__task} above is recommended.
+@noindent
+The above program is a valid StarPU program when StarPU's GCC plug-in is
+used; it is also a valid sequential program when the plug-in is not
+used.
+
+Note that attributes such as @code{task} as well as @code{starpu}
+pragmas are simply ignored by GCC when the StarPU plug-in is not loaded.
+However, @command{gcc -Wall} emits a warning for unknown attributes and
+pragmas, which can be inconvenient.  In addition, other compilers may be
+unable to parse the attribute syntax@footnote{In practice, Clang and
+several proprietary compilers implement attributes.}, so you may want to
+wrap attributes in macros like this:
+
+@smallexample
+/* Use the `task' attribute only when StarPU's GCC plug-in
+   is available.   */
+#ifdef STARPU_GCC_PLUGIN
+# define __task  __attribute__ ((task))
+#else
+# define __task
+#endif
+
+static void matmul (const float *A, const float *B, float *C,
+                    unsigned nx, unsigned ny, unsigned nz) __task;
+@end smallexample
+
 
 @c Local Variables:
 @c TeX-master: "../starpu.texi"