Bladeren bron

Add more 3D filters: vertical, depth, and shadow variants

Samuel Thibault 13 jaren geleden
bovenliggende
commit
ffed3ea57c

+ 91 - 45
doc/chapters/basic-api.texi

@@ -1130,39 +1130,69 @@ starpu_data_filter.
 @subsection Predefined filter functions
 
 @menu
-* Partitioning BCSR Data::
-* Partitioning BLAS interface::
 * Partitioning Vector Data::
-* Partitioning Block Data::
+* Partitioning Matrix Data::
+* Partitioning 3D Matrix Data::
+* Partitioning BCSR Data::
 @end menu
 
 This section gives a partial list of the predefined partitioning functions.
 Examples on how to use them are shown in @ref{Partitioning Data}. The complete
 list can be found in @code{starpu_data_filters.h} .
 
-@node Partitioning BCSR Data
-@subsubsection Partitioning BCSR Data
+@node Partitioning Vector Data
+@subsubsection Partitioning Vector Data
 
-@deftypefun void starpu_canonical_block_filter_bcsr (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-This partitions a block-sparse matrix into dense matrices.
+@deftypefun void starpu_block_filter_func_vector (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+Return in @code{*@var{child_interface}} the @var{id}th element of the
+vector represented by @var{father_interface} once partitioned in
+@var{nparts} chunks of equal size.
 @end deftypefun
 
-@deftypefun void starpu_vertical_block_filter_func_csr (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-This partitions a block-sparse matrix into vertical block-sparse matrices.
+@deftypefun void starpu_block_shadow_filter_func_vector (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+Return in @code{*@var{child_interface}} the @var{id}th element of the
+vector represented by @var{father_interface} once partitioned in
+@var{nparts} chunks of equal size with a shadow border @code{filter_arg_ptr}, thus getting a vector of size (n-2*shadow)/nparts+2*shadow 
+
+The @code{filter_arg_ptr} field must be the shadow size casted into @code{void*}.
+
+IMPORTANT: This can only be used for read-only access, as no coherency is
+enforced for the shadowed parts.
+
+A usage example is available in examples/filters/shadow.c
+@end deftypefun
+
+@deftypefun void starpu_vector_list_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+Return in @code{*@var{child_interface}} the @var{id}th element of the
+vector represented by @var{father_interface} once partitioned into
+@var{nparts} chunks according to the @code{filter_arg_ptr} field of
+@code{*@var{f}}.
+
+The @code{filter_arg_ptr} field must point to an array of @var{nparts}
+@code{uint32_t} elements, each of which specifies the number of elements
+in each chunk of the partition.
 @end deftypefun
 
-@node Partitioning BLAS interface
-@subsubsection Partitioning BLAS interface
+@deftypefun void starpu_vector_divide_in_2_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+Return in @code{*@var{child_interface}} the @var{id}th element of the
+vector represented by @var{father_interface} once partitioned in two
+chunks of equal size, ignoring @var{nparts}.  Thus, @var{id} must be
+@code{0} or @code{1}.
+@end deftypefun
+
+
+@node Partitioning Matrix Data
+@subsubsection Partitioning Matrix Data
 
 @deftypefun void starpu_block_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-This partitions a dense Matrix along the x dimension, thus getting (y,(x/nparts)
+This partitions a dense Matrix along the x dimension, thus getting (x/nparts,y)
 matrices. If nparts does not divide x, the last submatrix contains the
 remainder.
 @end deftypefun
 
 @deftypefun void starpu_block_shadow_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
 This partitions a dense Matrix along the x dimension, with a shadow border
-@code{filter_arg_ptr}, thus getting (y,((x-2*shadow)/nparts+2*shadow)
+@code{filter_arg_ptr}, thus getting ((x-2*shadow)/nparts+2*shadow,y)
 matrices. If nparts does not divide x-2*shadow, the last submatrix contains the
 remainder.
 
@@ -1173,14 +1203,14 @@ A usage example is available in examples/filters/shadow2d.c
 @end deftypefun
 
 @deftypefun void starpu_vertical_block_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-This partitions a dense Matrix along the y dimension, thus getting (y/nparts),x)
+This partitions a dense Matrix along the y dimension, thus getting (x,y/nparts)
 matrices. If nparts does not divide y, the last submatrix contains the
 remainder.
 @end deftypefun
 
 @deftypefun void starpu_vertical_block_shadow_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
 This partitions a dense Matrix along the y dimension, with a shadow border
-@code{filter_arg_ptr}, thus getting ((y-2*shadow)/nparts)+2*shadow,x)
+@code{filter_arg_ptr}, thus getting (x,(y-2*shadow)/nparts+2*shadow)
 matrices. If nparts does not divide y-2*shadow, the last submatrix contains the
 remainder.
 
@@ -1190,52 +1220,68 @@ enforced for the shadowed parts.
 A usage example is available in examples/filters/shadow2d.c
 @end deftypefun
 
-@node Partitioning Vector Data
-@subsubsection Partitioning Vector Data
+@node Partitioning 3D Matrix Data
+@subsubsection Partitioning 3D Matrix Data
 
-@deftypefun void starpu_block_filter_func_vector (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-Return in @code{*@var{child_interface}} the @var{id}th element of the
-vector represented by @var{father_interface} once partitioned in
-@var{nparts} chunks of equal size.
-@end deftypefun
+A usage example is available in examples/filters/shadow3d.c
 
-@deftypefun void starpu_block_shadow_filter_func_vector (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-Return in @code{*@var{child_interface}} the @var{id}th element of the
-vector represented by @var{father_interface} once partitioned in
-@var{nparts} chunks of equal size with a shadow border @code{filter_arg_ptr}, thus getting a vector of size (n-2*shadow)/nparts+2*shadow 
+@deftypefun void starpu_block_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the X dimension, thus getting (x/nparts,y,z)
+3D matrices. If nparts does not divide x, the last submatrix contains the
+remainder.
+@end deftypefun
 
-The @code{filter_arg_ptr} field must be the shadow size casted into @code{void*}.
+@deftypefun void starpu_block_shadow_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the X dimension, with a shadow border
+@code{filter_arg_ptr}, thus getting ((x-2*shadow)/nparts+2*shadow,y,z) 3D
+matrices. If nparts does not divide x, the last submatrix contains the
+remainder.
 
 IMPORTANT: This can only be used for read-only access, as no coherency is
 enforced for the shadowed parts.
+@end deftypefun
 
-A usage example is available in examples/filters/shadow.c
+@deftypefun void starpu_vertical_block_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the Y dimension, thus getting (x,y/nparts,z)
+3D matrices. If nparts does not divide y, the last submatrix contains the
+remainder.
 @end deftypefun
 
-@deftypefun void starpu_vector_list_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-Return in @code{*@var{child_interface}} the @var{id}th element of the
-vector represented by @var{father_interface} once partitioned into
-@var{nparts} chunks according to the @code{filter_arg_ptr} field of
-@code{*@var{f}}.
+@deftypefun void starpu_vertical_block_shadow_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the Y dimension, with a shadow border
+@code{filter_arg_ptr}, thus getting (x,(y-2*shadow)/nparts+2*shadow,z) 3D
+matrices. If nparts does not divide y, the last submatrix contains the
+remainder.
 
-The @code{filter_arg_ptr} field must point to an array of @var{nparts}
-@code{uint32_t} elements, each of which specifies the number of elements
-in each chunk of the partition.
+IMPORTANT: This can only be used for read-only access, as no coherency is
+enforced for the shadowed parts.
 @end deftypefun
 
-@deftypefun void starpu_vector_divide_in_2_filter_func (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-Return in @code{*@var{child_interface}} the @var{id}th element of the
-vector represented by @var{father_interface} once partitioned in two
-chunks of equal size, ignoring @var{nparts}.  Thus, @var{id} must be
-@code{0} or @code{1}.
+@deftypefun void starpu_depth_block_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the Z dimension, thus getting (x,y,z/nparts)
+3D matrices. If nparts does not divide z, the last submatrix contains the
+remainder.
+@end deftypefun
+
+@deftypefun void starpu_depth_block_shadow_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a 3D matrix along the Z dimension, with a shadow border
+@code{filter_arg_ptr}, thus getting (x,y,(z-2*shadow)/nparts+2*shadow)
+3D matrices. If nparts does not divide z, the last submatrix contains the
+remainder.
+
+IMPORTANT: This can only be used for read-only access, as no coherency is
+enforced for the shadowed parts.
 @end deftypefun
 
+@node Partitioning BCSR Data
+@subsubsection Partitioning BCSR Data
 
-@node Partitioning Block Data
-@subsubsection Partitioning Block Data
+@deftypefun void starpu_canonical_block_filter_bcsr (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a block-sparse matrix into dense matrices.
+@end deftypefun
 
-@deftypefun void starpu_block_filter_func_block (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
-This partitions a 3D matrix along the X axis.
+@deftypefun void starpu_vertical_block_filter_func_csr (void *@var{father_interface}, void *@var{child_interface}, {struct starpu_data_filter} *@var{f}, unsigned @var{id}, unsigned @var{nparts})
+This partitions a block-sparse matrix into vertical block-sparse matrices.
 @end deftypefun
 
 @node Codelets and Tasks

+ 1 - 0
examples/Makefile.am

@@ -181,6 +181,7 @@ examplebin_PROGRAMS +=				\
 	filters/fmatrix				\
 	filters/shadow				\
 	filters/shadow2d			\
+	filters/shadow3d			\
 	tag_example/tag_example			\
 	tag_example/tag_example2		\
 	tag_example/tag_example3		\

+ 335 - 0
examples/filters/shadow3d.c

@@ -0,0 +1,335 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2012  Université de Bordeaux 1
+ * Copyright (C) 2010, 2011, 2012  Centre National de la Recherche Scientifique
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU 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 Lesser General Public License in COPYING.LGPL for more details.
+ */
+
+/*
+ * This examplifies the use of the 3D matrix shadow filters: a source "matrix" of
+ * NX*NY*NZ elements (plus SHADOW wrap-around elements) is partitioned into
+ * matrices with some shadowing, and these are copied into a destination
+ * "matrix2" of
+ * NRPARTSX*NPARTSY*NPARTSZ*((NX/NPARTSX+2*SHADOWX)*(NY/NPARTSY+2*SHADOWY)*(NZ/NPARTSZ+2*SHADOWZ))
+ * elements, partitioned in the traditionnal way, thus showing how shadowing
+ * shows up.
+ */
+
+#include <starpu.h>
+#include <starpu_cuda.h>
+
+#warning Error on cudaMemcpy2D
+#undef STARPU_USE_CUDA
+
+/* Shadow width */
+#define SHADOWX 2
+#define SHADOWY 3
+#define SHADOWZ 4
+#define NX    12
+#define NY    9
+#define NZ    6
+#define PARTSX 4
+#define PARTSY 3
+#define PARTSZ 2
+
+#define FPRINTF(ofile, fmt, args ...) do { if (!getenv("STARPU_SSILENT")) {fprintf(ofile, fmt, ##args); }} while(0)
+
+void cpu_func(void *buffers[], void *cl_arg)
+{
+        /* length of the shadowed source matrix */
+        unsigned ldy = STARPU_BLOCK_GET_LDY(buffers[0]);
+        unsigned ldz = STARPU_BLOCK_GET_LDZ(buffers[0]);
+        unsigned x = STARPU_BLOCK_GET_NX(buffers[0]);
+        unsigned y = STARPU_BLOCK_GET_NY(buffers[0]);
+        unsigned z = STARPU_BLOCK_GET_NZ(buffers[0]);
+        /* local copy of the shadowed source matrix pointer */
+        int *val = (int *)STARPU_BLOCK_GET_PTR(buffers[0]);
+
+        /* length of the destination matrix */
+        unsigned ldy2 = STARPU_BLOCK_GET_LDY(buffers[1]);
+        unsigned ldz2 = STARPU_BLOCK_GET_LDZ(buffers[1]);
+        unsigned x2 = STARPU_BLOCK_GET_NX(buffers[1]);
+        unsigned y2 = STARPU_BLOCK_GET_NY(buffers[1]);
+        unsigned z2 = STARPU_BLOCK_GET_NZ(buffers[1]);
+        /* local copy of the destination matrix pointer */
+        int *val2 = (int *)STARPU_BLOCK_GET_PTR(buffers[1]);
+
+	unsigned i, j, k;
+
+	/* If things go right, sizes should match */
+	STARPU_ASSERT(x == x2);
+	STARPU_ASSERT(y == y2);
+	STARPU_ASSERT(z == z2);
+	for (k = 0; k < z; k++)
+		for (j = 0; j < y; j++)
+			for (i = 0; i < x; i++)
+				val2[k*ldz2+j*ldy2+i] = val[k*ldz+j*ldy+i];
+}
+
+#ifdef STARPU_USE_CUDA
+void cuda_func(void *buffers[], void *cl_arg)
+{
+        /* length of the shadowed source matrix */
+        unsigned ldy = STARPU_BLOCK_GET_LDY(buffers[0]);
+        unsigned ldz = STARPU_BLOCK_GET_LDZ(buffers[0]);
+        unsigned x = STARPU_BLOCK_GET_NX(buffers[0]);
+        unsigned y = STARPU_BLOCK_GET_NY(buffers[0]);
+        unsigned z = STARPU_BLOCK_GET_NZ(buffers[0]);
+        /* local copy of the shadowed source matrix pointer */
+        int *val = (int *)STARPU_BLOCK_GET_PTR(buffers[0]);
+
+        /* length of the destination matrix */
+        unsigned ldy2 = STARPU_BLOCK_GET_LDY(buffers[1]);
+        unsigned ldz2 = STARPU_BLOCK_GET_LDZ(buffers[1]);
+        unsigned x2 = STARPU_BLOCK_GET_NX(buffers[1]);
+        unsigned y2 = STARPU_BLOCK_GET_NY(buffers[1]);
+        unsigned z2 = STARPU_BLOCK_GET_NZ(buffers[1]);
+        /* local copy of the destination matrix pointer */
+        int *val2 = (int *)STARPU_BLOCK_GET_PTR(buffers[1]);
+
+	unsigned k;
+	cudaError_t cures;
+
+	/* If things go right, sizes should match */
+	STARPU_ASSERT(x == x2);
+	STARPU_ASSERT(y == y2);
+	STARPU_ASSERT(z == z2);
+	for (k = 0; k < z; k++) {
+		cures = cudaMemcpy2DAsync(val2+k*ldz2*sizeof(*val2), ldy2*sizeof(*val2), val+k*ldz*sizeof(*val), ldy*sizeof(*val),
+				x*sizeof(*val), y, cudaMemcpyDeviceToDevice, starpu_cuda_get_local_stream());
+		STARPU_ASSERT(!cures);
+	}
+	cures = cudaStreamSynchronize(starpu_cuda_get_local_stream());
+	STARPU_ASSERT(!cures);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+	unsigned i, j, k, l, m, n;
+        int matrix[NZ + 2*SHADOWZ][NY + 2*SHADOWY][NX + 2*SHADOWX];
+        int matrix2[NZ + PARTSZ*2*SHADOWZ][NY + PARTSY*2*SHADOWY][NX + PARTSX*2*SHADOWX];
+	starpu_data_handle_t handle, handle2;
+	int ret;
+
+        struct starpu_codelet cl =
+	{
+                .where = STARPU_CPU
+#ifdef STARPU_USE_CUDA
+			|STARPU_CUDA
+#endif
+			,
+                .cpu_funcs = {cpu_func, NULL},
+#ifdef STARPU_USE_CUDA
+                .cuda_funcs = {cuda_func, NULL},
+#endif
+                .nbuffers = 2,
+		.modes = {STARPU_R, STARPU_W}
+        };
+
+	memset(matrix, -1, sizeof(matrix));
+	for(k=1 ; k<=NZ ; k++)
+		for(j=1 ; j<=NY ; j++)
+			for(i=1 ; i<=NX ; i++)
+				matrix[SHADOWZ+k-1][SHADOWY+j-1][SHADOWX+i-1] = i+j+k;
+
+	/* Copy planes */
+	for (k = SHADOWZ ; k<SHADOWZ+NZ ; k++)
+		for (j = SHADOWY ; j<SHADOWY+NY ; j++)
+			for(i=0 ; i<SHADOWX ; i++) {
+				matrix[k][j][i] = matrix[k][j][i+NX];
+				matrix[k][j][SHADOWX+NX+i] = matrix[k][j][SHADOWX+i];
+			}
+	for(k=SHADOWZ ; k<SHADOWZ+NZ ; k++)
+		for(j=0 ; j<SHADOWY ; j++)
+			for(i=SHADOWX ; i<SHADOWX+NX ; i++) {
+				matrix[k][j][i] = matrix[k][j+NY][i];
+				matrix[k][SHADOWY+NY+j][i] = matrix[k][SHADOWY+j][i];
+			}
+	for(k=0 ; k<SHADOWZ ; k++)
+		for(j=SHADOWY ; j<SHADOWY+NY ; j++)
+			for(i=SHADOWX ; i<SHADOWX+NX ; i++) {
+				matrix[k][j][i] = matrix[k+NZ][j][i];
+				matrix[SHADOWZ+NZ+k][j][i] = matrix[SHADOWZ+k][j][i];
+			}
+
+	/* Copy borders */
+	for (k = SHADOWZ ; k<SHADOWZ+NZ ; k++)
+		for(j=0 ; j<SHADOWY ; j++)
+			for(i=0 ; i<SHADOWX ; i++) {
+				matrix[k][j][i] = matrix[k][j+NY][i+NX];
+				matrix[k][SHADOWY+NY+j][i] = matrix[k][SHADOWY+j][i+NX];
+				matrix[k][SHADOWY+NY+j][SHADOWX+NX+i] = matrix[k][SHADOWY+j][SHADOWX+i];
+				matrix[k][j][SHADOWX+NX+i] = matrix[k][j+NY][SHADOWX+i];
+			}
+	for(k=0 ; k<SHADOWZ ; k++)
+		for (j = SHADOWY ; j<SHADOWY+NY ; j++)
+			for(i=0 ; i<SHADOWX ; i++) {
+				matrix[k][j][i] = matrix[k+NZ][j][i+NX];
+				matrix[SHADOWZ+NZ+k][j][i] = matrix[SHADOWZ+k][j][i+NX];
+				matrix[SHADOWZ+NZ+k][j][SHADOWX+NX+i] = matrix[SHADOWZ+k][j][SHADOWX+i];
+				matrix[k][j][SHADOWX+NX+i] = matrix[k+NZ][j][SHADOWX+i];
+			}
+	for(k=0 ; k<SHADOWZ ; k++)
+		for(j=0 ; j<SHADOWY ; j++)
+			for(i=SHADOWX ; i<SHADOWX+NX ; i++) {
+				matrix[k][j][i] = matrix[k+NZ][j+NY][i];
+				matrix[SHADOWZ+NZ+k][j][i] = matrix[SHADOWZ+k][j+NY][i];
+				matrix[SHADOWZ+NZ+k][SHADOWY+NY+j][i] = matrix[SHADOWZ+k][SHADOWY+j][i];
+				matrix[k][SHADOWY+NY+j][i] = matrix[k+NZ][SHADOWY+j][i];
+			}
+
+	/* Copy corners */
+	for(k=0 ; k<SHADOWZ ; k++)
+		for(j=0 ; j<SHADOWY ; j++)
+			for(i=0 ; i<SHADOWX ; i++) {
+				matrix[k][j][i] = matrix[k+NZ][j+NY][i+NX];
+				matrix[k][j][SHADOWX+NX+i] = matrix[k+NZ][j+NY][SHADOWX+i];
+				matrix[k][SHADOWY+NY+j][i] = matrix[k+NZ][SHADOWY+j][i+NX];
+				matrix[k][SHADOWY+NY+j][SHADOWX+NX+i] = matrix[k+NZ][SHADOWY+j][SHADOWX+i];
+				matrix[SHADOWZ+NZ+k][j][i] = matrix[SHADOWZ+k][j+NY][i+NX];
+				matrix[SHADOWZ+NZ+k][j][SHADOWX+NX+i] = matrix[SHADOWZ+k][j+NY][SHADOWX+i];
+				matrix[SHADOWZ+NZ+k][SHADOWY+NY+j][i] = matrix[SHADOWZ+k][SHADOWY+j][i+NX];
+				matrix[SHADOWZ+NZ+k][SHADOWY+NY+j][SHADOWX+NX+i] = matrix[SHADOWZ+k][SHADOWY+j][SHADOWX+i];
+			}
+
+        FPRINTF(stderr,"IN  Matrix:\n");
+	for(k=0 ; k<NZ + 2*SHADOWZ ; k++)
+	{
+		for(j=0 ; j<NY + 2*SHADOWY ; j++)
+		{
+			for(i=0 ; i<NX + 2*SHADOWX ; i++)
+				FPRINTF(stderr, "%5d ", matrix[k][j][i]);
+			FPRINTF(stderr,"\n");
+		}
+		FPRINTF(stderr,"\n\n");
+	}
+        FPRINTF(stderr,"\n");
+
+	ret = starpu_init(NULL);
+	if (ret == -ENODEV)
+		exit(77);
+	STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
+
+	/* Declare source matrix to StarPU */
+	starpu_block_data_register(&handle, 0, (uintptr_t)matrix,
+			NX + 2*SHADOWX, (NX + 2*SHADOWX) * (NY + 2*SHADOWY),
+			NX + 2*SHADOWX, NY + 2*SHADOWY, NZ + 2*SHADOWZ,
+			sizeof(matrix[0][0][0]));
+
+	/* Declare destination matrix to StarPU */
+	starpu_block_data_register(&handle2, 0, (uintptr_t)matrix2,
+			NX + PARTSX*2*SHADOWX, (NX + PARTSX*2*SHADOWX) * (NY + PARTSY*2*SHADOWY),
+			NX + PARTSX*2*SHADOWX, NY + PARTSY*2*SHADOWY, NZ + PARTSZ*2*SHADOWZ,
+			sizeof(matrix2[0][0][0]));
+
+        /* Partition the source matrix in PARTSZ*PARTSY*PARTSX sub-matrices with shadows */
+	/* NOTE: the resulting handles should only be used in read-only mode,
+	 * as StarPU will not know how the overlapping parts would have to be
+	 * combined. */
+	struct starpu_data_filter fz =
+	{
+		.filter_func = starpu_depth_block_shadow_filter_func_block,
+		.nchildren = PARTSZ,
+		.filter_arg_ptr = (void*)(uintptr_t) SHADOWZ /* Shadow width */
+	};
+	struct starpu_data_filter fy =
+	{
+		.filter_func = starpu_vertical_block_shadow_filter_func_block,
+		.nchildren = PARTSY,
+		.filter_arg_ptr = (void*)(uintptr_t) SHADOWY /* Shadow width */
+	};
+	struct starpu_data_filter fx =
+	{
+		.filter_func = starpu_block_shadow_filter_func_block,
+		.nchildren = PARTSX,
+		.filter_arg_ptr = (void*)(uintptr_t) SHADOWX /* Shadow width */
+	};
+	starpu_data_map_filters(handle, 3, &fz, &fy, &fx);
+
+        /* Partition the destination matrix in PARTSZ*PARTSY*PARTSX sub-matrices */
+	struct starpu_data_filter fz2 =
+	{
+		.filter_func = starpu_depth_block_filter_func_block,
+		.nchildren = PARTSZ,
+	};
+	struct starpu_data_filter fy2 =
+	{
+		.filter_func = starpu_vertical_block_filter_func_block,
+		.nchildren = PARTSY,
+	};
+	struct starpu_data_filter fx2 =
+	{
+		.filter_func = starpu_block_filter_func_block,
+		.nchildren = PARTSX,
+	};
+	starpu_data_map_filters(handle2, 3, &fz2, &fy2, &fx2);
+
+        /* Submit a task on each sub-matrix */
+	for (k=0; k<PARTSZ; k++)
+	{
+		for (j=0; j<PARTSY; j++)
+		{
+			for (i=0; i<PARTSX; i++)
+			{
+				starpu_data_handle_t sub_handle = starpu_data_get_sub_data(handle, 3, k, j, i);
+				starpu_data_handle_t sub_handle2 = starpu_data_get_sub_data(handle2, 3, k, j, i);
+				struct starpu_task *task = starpu_task_create();
+
+				task->handles[0] = sub_handle;
+				task->handles[1] = sub_handle2;
+				task->cl = &cl;
+				task->synchronous = 1;
+
+				ret = starpu_task_submit(task);
+				if (ret == -ENODEV) goto enodev;
+				STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
+			}
+		}
+	}
+
+	starpu_data_unpartition(handle, 0);
+	starpu_data_unpartition(handle2, 0);
+        starpu_data_unregister(handle);
+        starpu_data_unregister(handle2);
+	starpu_shutdown();
+
+        FPRINTF(stderr,"OUT Matrix:\n");
+	for(k=0 ; k<NZ + PARTSZ*2*SHADOWZ ; k++)
+	{
+		for(j=0 ; j<NY + PARTSY*2*SHADOWY ; j++)
+		{
+			for(i=0 ; i<NX + PARTSX*2*SHADOWX ; i++) {
+				FPRINTF(stderr, "%5d ", matrix2[k][j][i]);
+			}
+			FPRINTF(stderr,"\n");
+		}
+		FPRINTF(stderr,"\n\n");
+	}
+        FPRINTF(stderr,"\n");
+	for(k=0 ; k<PARTSZ ; k++)
+		for(j=0 ; j<PARTSY ; j++)
+			for(i=0 ; i<PARTSX ; i++)
+				for (n=0 ; n<NZ/PARTSZ + 2*SHADOWZ ; n++)
+					for (m=0 ; m<NY/PARTSY + 2*SHADOWY ; m++)
+						for (l=0 ; l<NX/PARTSX + 2*SHADOWX ; l++)
+							STARPU_ASSERT(matrix2[k*(NZ/PARTSZ+2*SHADOWZ)+n][j*(NY/PARTSY+2*SHADOWY)+m][i*(NX/PARTSX+2*SHADOWX)+l] ==
+									matrix[k*(NZ/PARTSZ)+n][j*(NY/PARTSY)+m][i*(NX/PARTSX)+l]);
+
+	return 0;
+
+enodev:
+	FPRINTF(stderr, "WARNING: No one can execute this task\n");
+	starpu_shutdown();
+	return 77;
+}

+ 5 - 0
include/starpu_data_filters.h

@@ -75,6 +75,11 @@ void starpu_vector_divide_in_2_filter_func(void *father_interface, void *child_i
 
 /* for block */
 void starpu_block_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
+void starpu_block_shadow_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
+void starpu_vertical_block_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
+void starpu_vertical_block_shadow_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
+void starpu_depth_block_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
+void starpu_depth_block_shadow_filter_func_block(void *father_interface, void *child_interface, struct starpu_data_filter *f, unsigned id, unsigned nparts);
 
 #ifdef __cplusplus
 }

+ 182 - 2
src/datawizard/interfaces/block_filters.c

@@ -41,9 +41,189 @@ void starpu_block_filter_func_block(void *father_interface, void *child_interfac
 	block_child->nz = nz;
 	block_child->elemsize = elemsize;
 
-	if (block_father->ptr)
+	if (block_father->dev_handle)
 	{
-                block_child->ptr = block_father->ptr + offset;
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
+                block_child->ldy = block_father->ldy;
+                block_child->ldz = block_father->ldz;
+                block_child->dev_handle = block_father->dev_handle;
+                block_child->offset = block_father->offset + offset;
+	}
+}
+
+void starpu_block_shadow_filter_func_block(void *father_interface, void *child_interface, STARPU_ATTRIBUTE_UNUSED struct starpu_data_filter *f,
+                                    unsigned id, unsigned nparts)
+{
+        struct starpu_block_interface *block_father = (struct starpu_block_interface *) father_interface;
+        struct starpu_block_interface *block_child = (struct starpu_block_interface *) child_interface;
+
+        uintptr_t shadow_size = (uintptr_t) f->filter_arg_ptr;
+
+	/* actual number of elements */
+	uint32_t nx = block_father->nx - 2 * shadow_size;
+        uint32_t ny = block_father->ny;
+        uint32_t nz = block_father->nz;
+	size_t elemsize = block_father->elemsize;
+
+	STARPU_ASSERT(nparts <= nx);
+
+	uint32_t chunk_size = (nx + nparts - 1)/nparts;
+	size_t offset = id*chunk_size*elemsize;
+
+        uint32_t child_nx = STARPU_MIN(chunk_size, nx - id*chunk_size) + 2 * shadow_size;
+
+	block_child->nx = child_nx;
+	block_child->ny = ny;
+	block_child->nz = nz;
+	block_child->elemsize = elemsize;
+
+	if (block_father->dev_handle)
+	{
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
+                block_child->ldy = block_father->ldy;
+                block_child->ldz = block_father->ldz;
+                block_child->dev_handle = block_father->dev_handle;
+                block_child->offset = block_father->offset + offset;
+	}
+}
+
+void starpu_vertical_block_filter_func_block(void *father_interface, void *child_interface, STARPU_ATTRIBUTE_UNUSED struct starpu_data_filter *f,
+                                    unsigned id, unsigned nparts)
+{
+        struct starpu_block_interface *block_father = (struct starpu_block_interface *) father_interface;
+        struct starpu_block_interface *block_child = (struct starpu_block_interface *) child_interface;
+
+	uint32_t nx = block_father->nx;
+        uint32_t ny = block_father->ny;
+        uint32_t nz = block_father->nz;
+	size_t elemsize = block_father->elemsize;
+
+	STARPU_ASSERT(nparts <= ny);
+
+	uint32_t chunk_size = (ny + nparts - 1)/nparts;
+	size_t offset = id*chunk_size*block_father->ldy*elemsize;
+
+        uint32_t child_ny = STARPU_MIN(chunk_size, ny - id*chunk_size);
+
+	block_child->nx = nx;
+	block_child->ny = child_ny;
+	block_child->nz = nz;
+	block_child->elemsize = elemsize;
+
+	if (block_father->dev_handle)
+	{
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
+                block_child->ldy = block_father->ldy;
+                block_child->ldz = block_father->ldz;
+                block_child->dev_handle = block_father->dev_handle;
+                block_child->offset = block_father->offset + offset;
+	}
+}
+
+void starpu_vertical_block_shadow_filter_func_block(void *father_interface, void *child_interface, STARPU_ATTRIBUTE_UNUSED struct starpu_data_filter *f,
+                                    unsigned id, unsigned nparts)
+{
+        struct starpu_block_interface *block_father = (struct starpu_block_interface *) father_interface;
+        struct starpu_block_interface *block_child = (struct starpu_block_interface *) child_interface;
+
+        uintptr_t shadow_size = (uintptr_t) f->filter_arg_ptr;
+
+	uint32_t nx = block_father->nx;
+	/* actual number of elements */
+        uint32_t ny = block_father->ny - 2 * shadow_size;
+        uint32_t nz = block_father->nz;
+	size_t elemsize = block_father->elemsize;
+
+	STARPU_ASSERT(nparts <= ny);
+
+	uint32_t chunk_size = (ny + nparts - 1)/nparts;
+	size_t offset = id*chunk_size*block_father->ldy*elemsize;
+
+        uint32_t child_ny = STARPU_MIN(chunk_size, ny - id*chunk_size) + 2 * shadow_size;
+
+	block_child->nx = nx;
+	block_child->ny = child_ny;
+	block_child->nz = nz;
+	block_child->elemsize = elemsize;
+
+	if (block_father->dev_handle)
+	{
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
+                block_child->ldy = block_father->ldy;
+                block_child->ldz = block_father->ldz;
+                block_child->dev_handle = block_father->dev_handle;
+                block_child->offset = block_father->offset + offset;
+	}
+}
+
+void starpu_depth_block_filter_func_block(void *father_interface, void *child_interface, STARPU_ATTRIBUTE_UNUSED struct starpu_data_filter *f,
+                                    unsigned id, unsigned nparts)
+{
+        struct starpu_block_interface *block_father = (struct starpu_block_interface *) father_interface;
+        struct starpu_block_interface *block_child = (struct starpu_block_interface *) child_interface;
+
+	uint32_t nx = block_father->nx;
+        uint32_t ny = block_father->ny;
+        uint32_t nz = block_father->nz;
+	size_t elemsize = block_father->elemsize;
+
+	STARPU_ASSERT(nparts <= nz);
+
+	uint32_t chunk_size = (nz + nparts - 1)/nparts;
+	size_t offset = id*chunk_size*block_father->ldz*elemsize;
+
+        uint32_t child_nz = STARPU_MIN(chunk_size, nz - id*chunk_size);
+
+	block_child->nx = nx;
+	block_child->ny = ny;
+	block_child->nz = child_nz;
+	block_child->elemsize = elemsize;
+
+	if (block_father->dev_handle)
+	{
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
+                block_child->ldy = block_father->ldy;
+                block_child->ldz = block_father->ldz;
+                block_child->dev_handle = block_father->dev_handle;
+                block_child->offset = block_father->offset + offset;
+	}
+}
+
+void starpu_depth_block_shadow_filter_func_block(void *father_interface, void *child_interface, STARPU_ATTRIBUTE_UNUSED struct starpu_data_filter *f,
+                                    unsigned id, unsigned nparts)
+{
+        struct starpu_block_interface *block_father = (struct starpu_block_interface *) father_interface;
+        struct starpu_block_interface *block_child = (struct starpu_block_interface *) child_interface;
+
+        uintptr_t shadow_size = (uintptr_t) f->filter_arg_ptr;
+
+	uint32_t nx = block_father->nx;
+        uint32_t ny = block_father->ny;
+	/* actual number of elements */
+        uint32_t nz = block_father->nz - 2 * shadow_size;
+	size_t elemsize = block_father->elemsize;
+
+	STARPU_ASSERT(nparts <= nz);
+
+	uint32_t chunk_size = (nz + nparts - 1)/nparts;
+	size_t offset = id*chunk_size*block_father->ldz*elemsize;
+
+        uint32_t child_nz = STARPU_MIN(chunk_size, nz - id*chunk_size) + 2 * shadow_size;
+
+	block_child->nx = nx;
+	block_child->ny = ny;
+	block_child->nz = child_nz;
+	block_child->elemsize = elemsize;
+
+	if (block_father->dev_handle)
+	{
+		if (block_father->ptr)
+                	block_child->ptr = block_father->ptr + offset;
                 block_child->ldy = block_father->ldy;
                 block_child->ldz = block_father->ldz;
                 block_child->dev_handle = block_father->dev_handle;