Explorar el Código

- add Fortran support for dynamic buffers
- move fstarpu_insert_task to starpu_task_insert_utils.c to avoid duplicating code

Olivier Aumage hace 9 años
padre
commit
f6e0e65d4f
Se han modificado 4 ficheros con 413 adiciones y 274 borrados
  1. 1 1
      examples/native_fortran/nf_vector.f90
  2. 70 0
      include/fstarpu_mod.f90
  3. 57 204
      src/util/fstarpu.c
  4. 285 69
      src/util/starpu_task_insert_utils.c

+ 1 - 1
examples/native_fortran/nf_vector.f90

@@ -61,7 +61,7 @@ program nf_vector
         call fstarpu_codelet_add_buffer(cl_vec, FSTARPU_R)
 
         ! add a Read-Write mode data buffer to the codelet
-        call fstarpu_codelet_add_buffer(cl_vec, FSTARPU_RW)
+        call fstarpu_codelet_add_buffer(cl_vec, FSTARPU_RW.ior.FSTARPU_LOCALITY)
 
         ! register 'va', a vector of real(8) elements
         call fstarpu_vector_data_register(dh_va, 0, c_loc(va), 1+ubound(va,1)-lbound(va,1), c_sizeof(va(lbound(va,1))))

+ 70 - 0
include/fstarpu_mod.f90

@@ -647,6 +647,12 @@ module fstarpu_mod
                         type(c_ptr), value, intent(in) :: mode ! C function expects an intptr_t
                 end subroutine fstarpu_codelet_add_buffer
 
+                subroutine fstarpu_codelet_set_nbuffers (cl, nbuffers) bind(C)
+                        use iso_c_binding, only: c_ptr,c_int
+                        type(c_ptr), value, intent(in) :: cl
+                        integer(c_int), value, intent(in) :: nbuffers
+                end subroutine fstarpu_codelet_set_nbuffers
+
                 ! == starpu_data_interface.h ==
 
                 ! uintptr_t starpu_malloc_on_node_flags(unsigned dst_node, size_t size, int flags);
@@ -1345,6 +1351,70 @@ module fstarpu_mod
                 end subroutine fstarpu_memchunk_tidy
 
                 ! == starpu_task_util.h ==
+                ! struct starpu_data_handle *fstarpu_data_handle_array_alloc(int nb);
+                function fstarpu_data_handle_array_alloc (nb) bind(C)
+                        use iso_c_binding, only: c_ptr, c_int
+                        type(c_ptr) :: fstarpu_data_handle_array_alloc
+                        integer(c_int), value, intent(in) :: nb
+                end function fstarpu_data_handle_array_alloc
+
+                ! void fstarpu_data_handle_array_free(starpu_data_handle_t *handles);
+                subroutine fstarpu_data_handle_array_free (handles) bind(C)
+                        use iso_c_binding, only: c_ptr
+                        type(c_ptr), value, intent(in) :: handles
+                end subroutine fstarpu_data_handle_array_free
+
+                ! void fstarpu_data_handle_array_set(starpu_data_handle_t *handles, int i, starpu_data_handle_t handle);
+                subroutine fstarpu_data_handle_array_set (handles, i, handle) bind(C)
+                        use iso_c_binding, only: c_ptr, c_int
+                        type(c_ptr), value, intent(in) :: handles
+                        integer(c_int), value, intent(in) :: i
+                        type(c_ptr), value, intent(in) :: handle
+                end subroutine fstarpu_data_handle_array_set
+
+                ! struct starpu_data_descr *fstarpu_data_descr_array_alloc(int nb);
+                function fstarpu_data_descr_array_alloc (nb) bind(C)
+                        use iso_c_binding, only: c_ptr, c_int
+                        type(c_ptr) :: fstarpu_data_descr_array_alloc
+                        integer(c_int), value, intent(in) :: nb
+                end function fstarpu_data_descr_array_alloc
+
+                ! struct starpu_data_descr *fstarpu_data_descr_alloc(void);
+                function fstarpu_data_descr_alloc (nb) bind(C)
+                        use iso_c_binding, only: c_ptr
+                        type(c_ptr) :: fstarpu_data_descr_alloc
+                end function fstarpu_data_descr_alloc
+
+                ! void fstarpu_data_descr_array_free(struct starpu_data_descr *descrs);
+                subroutine fstarpu_data_descr_array_free (descrs) bind(C)
+                        use iso_c_binding, only: c_ptr
+                        type(c_ptr), value, intent(in) :: descrs
+                end subroutine fstarpu_data_descr_array_free
+
+                ! void fstarpu_data_descr_free(struct starpu_data_descr *descr);
+                subroutine fstarpu_data_descrg_free (descr) bind(C)
+                        use iso_c_binding, only: c_ptr
+                        type(c_ptr), value, intent(in) :: descr
+                end subroutine fstarpu_data_descrg_free
+
+                ! void fstarpu_data_descr_array_set(struct starpu_data_descr *descrs, int i, starpu_data_handle_t handle, intptr_t mode);
+                subroutine fstarpu_data_descr_array_set (descrs, i, handle, mode) bind(C)
+                        use iso_c_binding, only: c_ptr, c_int, c_intptr_t
+                        type(c_ptr), value, intent(in) :: descrs
+                        integer(c_int), value, intent(in) :: i
+                        type(c_ptr), value, intent(in) :: handle
+                        integer(c_intptr_t), value, intent(in) :: mode
+                end subroutine fstarpu_data_descr_array_set
+
+                ! void fstarpu_data_descr_set(struct starpu_data_descr *descr, starpu_data_handle_t handle, intptr_t mode);
+                subroutine fstarpu_data_descr_set (descr, handle, mode) bind(C)
+                        use iso_c_binding, only: c_ptr, c_intptr_t
+                        type(c_ptr), value, intent(in) :: descr
+                        type(c_ptr), value, intent(in) :: handle
+                        integer(c_intptr_t), value, intent(in) :: mode
+                end subroutine fstarpu_data_descr_set
+
+
                 subroutine fstarpu_insert_task(arglist) bind(C)
                         use iso_c_binding, only: c_ptr
                         type(c_ptr), dimension(:), intent(in) :: arglist

+ 57 - 204
src/util/fstarpu.c

@@ -65,8 +65,6 @@ static const intptr_t fstarpu_mic_worker = STARPU_MIC_WORKER;
 static const intptr_t fstarpu_scc_worker = STARPU_SCC_WORKER;
 static const intptr_t fstarpu_any_worker = STARPU_ANY_WORKER;
 
-extern void _starpu_pack_arguments(size_t *current_offset, size_t *arg_buffer_size_, char **arg_buffer_, void *ptr, size_t ptr_size);
-
 intptr_t fstarpu_get_constant(char *s)
 {
 	if	(!strcmp(s, "FSTARPU_R"))	{ return fstarpu_r; }
@@ -282,14 +280,12 @@ void fstarpu_codelet_add_scc_func(struct starpu_codelet *cl, void *f_ptr)
 	_FSTARPU_ERROR("fstarpu: too many scc functions in Fortran codelet");
 }
 
-void fstarpu_codelet_add_buffer(struct starpu_codelet *cl, intptr_t mode)
+void fstarpu_codelet_add_buffer(struct starpu_codelet *cl, intptr_t _mode)
 {
+
+	enum starpu_data_access_mode mode = (enum starpu_data_access_mode) _mode;
 	const size_t max_modes = sizeof(cl->modes)/sizeof(cl->modes[0])-1;
-	if (mode !=  fstarpu_r
-		&& mode != fstarpu_rw
-		&& mode != fstarpu_w
-		&& mode != fstarpu_scratch
-		&& mode != fstarpu_redux)
+	if ((mode & (STARPU_ACCESS_MODE_MAX-1)) != mode)
 	{
 		_FSTARPU_ERROR("fstarpu: invalid data mode");
 	}
@@ -304,6 +300,18 @@ void fstarpu_codelet_add_buffer(struct starpu_codelet *cl, intptr_t mode)
 	}
 }
 
+void fstarpu_codelet_set_nbuffers(struct starpu_codelet *cl, int nbuffers)
+{
+	if (nbuffers >= 0)
+	{
+		cl->nbuffers = nbuffers;
+	}
+	else
+	{
+		_FSTARPU_ERROR("fstarpu: invalid nbuffers parameter");
+	}
+}
+
 void * fstarpu_variable_get_ptr(void *buffers[], int i)
 {
 	return (void *)STARPU_VECTOR_GET_PTR(buffers[i]);
@@ -444,203 +452,48 @@ void fstarpu_worker_get_type_as_string(intptr_t type, char *dst, size_t maxlen)
 	snprintf(dst, maxlen, "%s", str);
 }
 
-void fstarpu_insert_task(void ***_arglist)
+struct starpu_data_handle *fstarpu_data_handle_array_alloc(int nb)
 {
-	void **arglist = *_arglist;
-	int i = 0;
-	char *arg_buffer_ = NULL;
-	size_t arg_buffer_size_ = 0;
-	size_t current_offset = sizeof(int);
-	int current_buffer = 0;
-	int nargs = 0;
-	struct starpu_task *task = NULL;
-	struct starpu_codelet *cl = arglist[i++];
-	if (cl == NULL)
-	{
-		_FSTARPU_ERROR("task without codelet");
-	}
-	task = starpu_task_create();
-	task->cl = cl;
-	task->name = NULL;
-	while (arglist[i] != NULL)
-	{
-		const intptr_t arg_type = (intptr_t)arglist[i];
-		if (arg_type & fstarpu_r
-			|| arg_type & fstarpu_w
-			|| arg_type & fstarpu_scratch
-			|| arg_type & fstarpu_redux)
-		{
-			i++;
-			starpu_data_handle_t handle = arglist[i];
-			if (current_buffer >= cl->nbuffers)
-			{
-				_FSTARPU_ERROR("too many buffers");
-			}
-			STARPU_TASK_SET_HANDLE(task, handle, current_buffer);
-			if (!STARPU_CODELET_GET_MODE(cl, current_buffer))
-			{
-				_FSTARPU_ERROR("unsupported late access mode definition");
-			}
-			current_buffer++;
-		}
-		//else if (arg_type == fstarpu_data_array)
-		//{
-		//}
-		//else if (arg_type == fstarpu_data_mode_array)
-		//{
-		//}
-		else if (arg_type == fstarpu_value)
-		{
-			i++;
-			void *ptr = arglist[i];
-			i++;
-			size_t ptr_size = (size_t)(intptr_t)arglist[i];
-			nargs++;
-			_starpu_pack_arguments(&current_offset, &arg_buffer_size_, &arg_buffer_, ptr, ptr_size);
-		}
-		else if (arg_type == fstarpu_cl_args)
-		{
-			i++;
-			task->cl_arg = arglist[i];
-			i++;
-			task->cl_arg_size = (size_t)(intptr_t)arglist[i];
-			task->cl_arg_free = 1;
-		}
-		else if (arg_type == fstarpu_callback)
-		{
-			i++;
-			task->callback_func = (_starpu_callback_func_t)arglist[i];
-		}
-		else if (arg_type == fstarpu_callback_with_arg)
-		{
-			i++;
-			task->callback_func = (_starpu_callback_func_t)arglist[i];
-			i++;
-			task->callback_arg = arglist[i];
-		}
-		else if (arg_type == fstarpu_callback_arg)
-		{
-			i++;
-			task->callback_arg = arglist[i];
-		}
-		else if (arg_type == fstarpu_prologue_callback)
-		{
-			i++;
-			task->prologue_callback_func = (_starpu_callback_func_t)arglist[i];
-		}
-		else if (arg_type == fstarpu_prologue_callback_arg)
-		{
-			i++;
-			task->prologue_callback_arg = arglist[i];
-		}
-		else if (arg_type == fstarpu_prologue_callback_pop)
-		{
-			i++;
-			task->prologue_callback_pop_func = (_starpu_callback_func_t)arglist[i];
-		}
-		else if (arg_type == fstarpu_prologue_callback_pop_arg)
-		{
-			i++;
-			task->prologue_callback_pop_arg = arglist[i];
-		}
-		else if (arg_type == fstarpu_priority)
-		{
-			i++;
-			task->priority = *(int *)arglist[i];
-		}
-		else if (arg_type == fstarpu_execute_on_node)
-		{
-			i++;
-			(void)arglist[i];
-		}
-		else if (arg_type == fstarpu_execute_on_data)
-		{
-			i++;
-			(void)arglist[i];
-		}
-		else if (arg_type == fstarpu_execute_on_worker)
-		{
-			i++;
-			int worker = *(int *)arglist[i];
-			if (worker != -1)
-			{
-				task->workerid = worker;
-				task->execute_on_a_specific_worker = 1;
-			}
-		}
-		else if (arg_type == fstarpu_worker_order)
-		{
-			i++;
-			unsigned order = *(unsigned *)arglist[i];
-			if (order != 0)
-			{
-				STARPU_ASSERT_MSG(task->execute_on_a_specific_worker, "worker order only makes sense if a workerid is provided");
-				task->workerorder = order;
-			}
-		}
-		else if (arg_type == fstarpu_sched_ctx)
-		{
-			i++;
-			task->sched_ctx = *(unsigned *)arglist[i];
-		}
-		else if (arg_type == fstarpu_hypervisor_tag)
-		{
-			i++;
-			task->hypervisor_tag = *(int *)arglist[i];
-		}
-		else if (arg_type == fstarpu_possibly_parallel)
-		{
-			i++;
-			task->possibly_parallel = *(unsigned *)arglist[i];
-		}
-		else if (arg_type == fstarpu_flops)
-		{
-			i++;
-			task->flops = *(double *)arglist[i];
-		}
-		else if (arg_type == fstarpu_tag)
-		{
-			i++;
-			task->tag_id = *(starpu_tag_t *)arglist[i];
-			task->use_tag = 1;
-		}
-		else if (arg_type == fstarpu_tag_only)
-		{
-			i++;
-			task->tag_id = *(starpu_tag_t *)arglist[i];
-		}
-		else if (arg_type == fstarpu_name)
-		{
-			i++;
-			task->name = arglist[i];
-		}
-		else if (arg_type == fstarpu_node_selection_policy)
-		{
-			i++;
-			(void)arglist[i];
-		}
-		else
-		{
-			_FSTARPU_ERROR("unknown/unsupported argument type");
-		}
-		i++;
-	}
+	return calloc((size_t)nb, sizeof(starpu_data_handle_t));
+}
 
-	if (nargs)
-	{
-		memcpy(arg_buffer_, (int *)&nargs, sizeof(nargs));
-		task->cl_arg = arg_buffer_;
-		task->cl_arg_size = arg_buffer_size_;
-	}
-	else
-	{
-		free(arg_buffer_);
-		arg_buffer_ = NULL;
-	}
+void fstarpu_data_handle_array_free(starpu_data_handle_t *handles)
+{
+	free(handles);
+}
 
-	int ret = starpu_task_submit(task);
-	if (ret != 0)
-	{
-		_FSTARPU_ERROR("starpu_task_submit failed");
-	}
+void fstarpu_data_handle_array_set(starpu_data_handle_t *handles, int i, starpu_data_handle_t handle)
+{
+	handles[i] = handle;
+}
+
+struct starpu_data_descr *fstarpu_data_descr_array_alloc(int nb)
+{
+	return calloc((size_t)nb, sizeof(struct starpu_data_descr));
+}
+
+struct starpu_data_descr *fstarpu_data_descr_alloc(void)
+{
+	return fstarpu_data_descr_array_alloc(1);
+}
+
+void fstarpu_data_descr_array_free(struct starpu_data_descr *descrs)
+{
+	free(descrs);
+}
+
+void fstarpu_data_descr_free(struct starpu_data_descr *descr)
+{
+	fstarpu_data_descr_array_free(descr);
+}
+
+void fstarpu_data_descr_array_set(struct starpu_data_descr *descrs, int i, starpu_data_handle_t handle, intptr_t mode)
+{
+	descrs[i].handle = handle;
+	descrs[i].mode = (enum starpu_data_access_mode)mode;
+}
+
+void fstarpu_data_descr_set(struct starpu_data_descr *descr, starpu_data_handle_t handle, intptr_t mode)
+{
+	fstarpu_data_descr_array_set(descr, 1, handle, mode);
 }

+ 285 - 69
src/util/starpu_task_insert_utils.c

@@ -21,7 +21,7 @@
 #include <common/utils.h>
 #include <core/task.h>
 
-void _starpu_pack_arguments(size_t *current_offset, size_t *arg_buffer_size_, char **arg_buffer_, void *ptr, size_t ptr_size)
+static void _starpu_pack_arguments(size_t *current_offset, size_t *arg_buffer_size_, char **arg_buffer_, void *ptr, size_t ptr_size)
 {
 	if (*current_offset + sizeof(ptr_size) + ptr_size > *arg_buffer_size_)
 	{
@@ -209,6 +209,83 @@ void _starpu_task_insert_check_nb_buffers(struct starpu_codelet *cl, struct star
 	}
 }
 
+static inline void starpu_task_insert_process_data_arg(struct starpu_codelet *cl, struct starpu_task **task, int arg_type, starpu_data_handle_t handle, int *current_buffer, int *allocated_buffers)
+{
+	enum starpu_data_access_mode mode = (enum starpu_data_access_mode) arg_type & ~STARPU_SSEND;
+	STARPU_ASSERT_MSG(cl->nbuffers == STARPU_VARIABLE_NBUFFERS || *current_buffer < cl->nbuffers, "Too many data passed to starpu_task_insert");
+
+	STARPU_ASSERT(cl != NULL);
+
+	_starpu_task_insert_check_nb_buffers(cl, task, allocated_buffers, *current_buffer);
+
+	STARPU_TASK_SET_HANDLE((*task), handle, *current_buffer);
+	if (cl->nbuffers == STARPU_VARIABLE_NBUFFERS || (cl->nbuffers > STARPU_NMAXBUFS && !cl->dyn_modes))
+		STARPU_TASK_SET_MODE(*task, mode,* current_buffer);
+	else if (STARPU_CODELET_GET_MODE(cl, *current_buffer))
+	{
+		STARPU_ASSERT_MSG(STARPU_CODELET_GET_MODE(cl, *current_buffer) == mode,
+				"The codelet <%s> defines the access mode %d for the buffer %d which is different from the mode %d given to starpu_task_insert\n",
+				cl->name, STARPU_CODELET_GET_MODE(cl, *current_buffer),
+				*current_buffer, mode);
+	}
+	else
+	{
+#ifdef STARPU_DEVEL
+#  warning shall we print a warning to the user
+		/* Morse uses it to avoid having to set it in the codelet structure */
+#endif
+		STARPU_CODELET_SET_MODE(cl, mode, *current_buffer);
+	}
+
+	(*current_buffer)++;
+}
+
+static inline void starpu_task_insert_process_data_array_arg(struct starpu_codelet *cl, struct starpu_task **task, int nb_handles, starpu_data_handle_t *handles, int *current_buffer, int *allocated_buffers)
+{
+	STARPU_ASSERT(cl != NULL);
+
+	int i;
+	for(i=0 ; i<nb_handles ; i++)
+	{
+		_starpu_task_insert_check_nb_buffers(cl, task, allocated_buffers, *current_buffer);
+		STARPU_TASK_SET_HANDLE((*task), handles[i], *current_buffer);
+		(*current_buffer)++;
+	}
+}
+
+static inline void starpu_task_insert_process_data_mode_array_arg(struct starpu_codelet *cl, struct starpu_task **task, int nb_descrs, struct starpu_data_descr *descrs, int *current_buffer, int *allocated_buffers)
+{
+	STARPU_ASSERT(cl != NULL);
+
+	int i;
+	for(i=0 ; i<nb_descrs ; i++)
+	{
+		STARPU_ASSERT_MSG(cl->nbuffers == STARPU_VARIABLE_NBUFFERS || *current_buffer < cl->nbuffers, "Too many data passed to starpu_task_insert");
+		_starpu_task_insert_check_nb_buffers(cl, task, allocated_buffers, *current_buffer);
+		STARPU_TASK_SET_HANDLE((*task), descrs[i].handle, *current_buffer);
+		if ((*task)->dyn_modes)
+		{
+			(*task)->dyn_modes[*current_buffer] = descrs[i].mode;
+		}
+		else if (cl->nbuffers == STARPU_VARIABLE_NBUFFERS || (cl->nbuffers > STARPU_NMAXBUFS && !cl->dyn_modes))
+			STARPU_TASK_SET_MODE(*task, descrs[i].mode, *current_buffer);
+		else if (STARPU_CODELET_GET_MODE(cl, *current_buffer))
+		{
+			STARPU_ASSERT_MSG(STARPU_CODELET_GET_MODE(cl, *current_buffer) == descrs[i].mode,
+					"The codelet <%s> defines the access mode %d for the buffer %d which is different from the mode %d given to starpu_task_insert\n",
+					cl->name, STARPU_CODELET_GET_MODE(cl, *current_buffer),
+					*current_buffer, descrs[i].mode);
+		}
+		else
+		{
+			STARPU_CODELET_SET_MODE(cl, descrs[i].mode, *current_buffer);
+		}
+
+		(*current_buffer)++;
+	}
+
+}
+
 int _starpu_task_insert_create(struct starpu_codelet *cl, struct starpu_task **task, va_list varg_list)
 {
 	int arg_type;
@@ -230,86 +307,21 @@ int _starpu_task_insert_create(struct starpu_codelet *cl, struct starpu_task **t
 		{
 			/* We have an access mode : we expect to find a handle */
 			starpu_data_handle_t handle = va_arg(varg_list, starpu_data_handle_t);
-			enum starpu_data_access_mode mode = (enum starpu_data_access_mode) arg_type & ~STARPU_SSEND;
-			STARPU_ASSERT_MSG(cl->nbuffers == STARPU_VARIABLE_NBUFFERS || current_buffer < cl->nbuffers, "Too many data passed to starpu_task_insert");
-
-			STARPU_ASSERT(cl != NULL);
-
-			_starpu_task_insert_check_nb_buffers(cl, task, &allocated_buffers, current_buffer);
-
-			STARPU_TASK_SET_HANDLE((*task), handle, current_buffer);
-			if (cl->nbuffers == STARPU_VARIABLE_NBUFFERS || (cl->nbuffers > STARPU_NMAXBUFS && !cl->dyn_modes))
-				STARPU_TASK_SET_MODE(*task, mode, current_buffer);
-			else if (STARPU_CODELET_GET_MODE(cl, current_buffer))
-			{
-				STARPU_ASSERT_MSG(STARPU_CODELET_GET_MODE(cl, current_buffer) == mode,
-						   "The codelet <%s> defines the access mode %d for the buffer %d which is different from the mode %d given to starpu_task_insert\n",
-						  cl->name, STARPU_CODELET_GET_MODE(cl, current_buffer),
-						  current_buffer, mode);
-			}
-			else
-			{
-#ifdef STARPU_DEVEL
-#  warning shall we print a warning to the user
-/* Morse uses it to avoid having to set it in the codelet structure */
-#endif
-				STARPU_CODELET_SET_MODE(cl, mode, current_buffer);
-			}
-
-			current_buffer++;
+			starpu_task_insert_process_data_arg(cl, task, arg_type, handle, &current_buffer, &allocated_buffers);
 		}
 		else if (arg_type == STARPU_DATA_ARRAY)
 		{
 			// Expect to find a array of handles and its size
 			starpu_data_handle_t *handles = va_arg(varg_list, starpu_data_handle_t *);
 			int nb_handles = va_arg(varg_list, int);
-
-			STARPU_ASSERT(cl != NULL);
-
-			int i;
-			for(i=0 ; i<nb_handles ; i++)
-			{
-				_starpu_task_insert_check_nb_buffers(cl, task, &allocated_buffers, current_buffer);
-				STARPU_TASK_SET_HANDLE((*task), handles[i], current_buffer);
-				current_buffer++;
-			}
-
+			starpu_task_insert_process_data_array_arg(cl, task, nb_handles, handles, &current_buffer, &allocated_buffers);
 		}
 		else if (arg_type==STARPU_DATA_MODE_ARRAY)
 		{
 			// Expect to find a array of descr and its size
 			struct starpu_data_descr *descrs = va_arg(varg_list, struct starpu_data_descr *);
 			int nb_descrs = va_arg(varg_list, int);
-
-			STARPU_ASSERT(cl != NULL);
-
-			int i;
-			for(i=0 ; i<nb_descrs ; i++)
-			{
-				STARPU_ASSERT_MSG(cl->nbuffers == STARPU_VARIABLE_NBUFFERS || current_buffer < cl->nbuffers, "Too many data passed to starpu_task_insert");
-				_starpu_task_insert_check_nb_buffers(cl, task, &allocated_buffers, current_buffer);
-				STARPU_TASK_SET_HANDLE((*task), descrs[i].handle, current_buffer);
-				if ((*task)->dyn_modes)
-				{
-					(*task)->dyn_modes[current_buffer] = descrs[i].mode;
-				}
-				else if (cl->nbuffers == STARPU_VARIABLE_NBUFFERS || (cl->nbuffers > STARPU_NMAXBUFS && !cl->dyn_modes))
-					STARPU_TASK_SET_MODE(*task, descrs[i].mode, current_buffer);
-				else if (STARPU_CODELET_GET_MODE(cl, current_buffer))
-				{
-					STARPU_ASSERT_MSG(STARPU_CODELET_GET_MODE(cl, current_buffer) == descrs[i].mode,
-							  "The codelet <%s> defines the access mode %d for the buffer %d which is different from the mode %d given to starpu_task_insert\n",
-							  cl->name, STARPU_CODELET_GET_MODE(cl, current_buffer),
-							  current_buffer, descrs[i].mode);
-				}
-				else
-				{
-					STARPU_CODELET_SET_MODE(cl, descrs[i].mode, current_buffer);
-				}
-
-				current_buffer++;
-			}
-
+			starpu_task_insert_process_data_mode_array_arg(cl, task, nb_descrs, descrs, &current_buffer, &allocated_buffers);
 		}
 		else if (arg_type==STARPU_VALUE)
 		{
@@ -466,3 +478,207 @@ int _starpu_task_insert_create(struct starpu_codelet *cl, struct starpu_task **t
 	_STARPU_TRACE_TASK_BUILD_END();
 	return 0;
 }
+
+/* Fortran interface to insert_task */
+void fstarpu_insert_task(void ***_arglist)
+{
+	void **arglist = *_arglist;
+	int i = 0;
+	char *arg_buffer_ = NULL;
+	size_t arg_buffer_size_ = 0;
+	size_t current_offset = sizeof(int);
+	int current_buffer = 0;
+	int nargs = 0;
+	int allocated_buffers = 0;
+	struct starpu_task *task = NULL;
+	struct starpu_codelet *cl = arglist[i++];
+	if (cl == NULL)
+	{
+		STARPU_ABORT_MSG("task without codelet");
+	}
+	task = starpu_task_create();
+	task->cl = cl;
+	task->name = NULL;
+	while (arglist[i] != NULL)
+	{
+		const int arg_type = (int)(intptr_t)arglist[i];
+		if (arg_type & STARPU_R
+			|| arg_type & STARPU_W
+			|| arg_type & STARPU_SCRATCH
+			|| arg_type & STARPU_REDUX)
+		{
+			i++;
+			starpu_data_handle_t handle = arglist[i];
+			starpu_task_insert_process_data_arg(cl, &task, arg_type, handle, &current_buffer, &allocated_buffers);
+		}
+		else if (arg_type == STARPU_DATA_ARRAY)
+		{
+			i++;
+			starpu_data_handle_t *handles = arglist[i];
+			i++;
+			int nb_handles = *(int *)arglist[i];
+			starpu_task_insert_process_data_array_arg(cl, &task, nb_handles, handles, &current_buffer, &allocated_buffers);
+		}
+		else if (arg_type == STARPU_DATA_MODE_ARRAY)
+		{
+			i++;
+			struct starpu_data_descr *descrs = arglist[i];
+			i++;
+			int nb_descrs = *(int *)arglist[i];
+			starpu_task_insert_process_data_mode_array_arg(cl, &task, nb_descrs, descrs, &current_buffer, &allocated_buffers);
+		}
+		else if (arg_type == STARPU_VALUE)
+		{
+			i++;
+			void *ptr = arglist[i];
+			i++;
+			size_t ptr_size = (size_t)(intptr_t)arglist[i];
+			nargs++;
+			_starpu_pack_arguments(&current_offset, &arg_buffer_size_, &arg_buffer_, ptr, ptr_size);
+		}
+		else if (arg_type == STARPU_CL_ARGS)
+		{
+			i++;
+			task->cl_arg = arglist[i];
+			i++;
+			task->cl_arg_size = (size_t)(intptr_t)arglist[i];
+			task->cl_arg_free = 1;
+		}
+		else if (arg_type == STARPU_CALLBACK)
+		{
+			i++;
+			task->callback_func = (_starpu_callback_func_t)arglist[i];
+		}
+		else if (arg_type == STARPU_CALLBACK_WITH_ARG)
+		{
+			i++;
+			task->callback_func = (_starpu_callback_func_t)arglist[i];
+			i++;
+			task->callback_arg = arglist[i];
+		}
+		else if (arg_type == STARPU_CALLBACK_ARG)
+		{
+			i++;
+			task->callback_arg = arglist[i];
+		}
+		else if (arg_type == STARPU_PROLOGUE_CALLBACK)
+		{
+			i++;
+			task->prologue_callback_func = (_starpu_callback_func_t)arglist[i];
+		}
+		else if (arg_type == STARPU_PROLOGUE_CALLBACK_ARG)
+		{
+			i++;
+			task->prologue_callback_arg = arglist[i];
+		}
+		else if (arg_type == STARPU_PROLOGUE_CALLBACK_POP)
+		{
+			i++;
+			task->prologue_callback_pop_func = (_starpu_callback_func_t)arglist[i];
+		}
+		else if (arg_type == STARPU_PROLOGUE_CALLBACK_POP_ARG)
+		{
+			i++;
+			task->prologue_callback_pop_arg = arglist[i];
+		}
+		else if (arg_type == STARPU_PRIORITY)
+		{
+			i++;
+			task->priority = *(int *)arglist[i];
+		}
+		else if (arg_type == STARPU_EXECUTE_ON_NODE)
+		{
+			i++;
+			(void)arglist[i];
+		}
+		else if (arg_type == STARPU_EXECUTE_ON_DATA)
+		{
+			i++;
+			(void)arglist[i];
+		}
+		else if (arg_type == STARPU_EXECUTE_ON_WORKER)
+		{
+			i++;
+			int worker = *(int *)arglist[i];
+			if (worker != -1)
+			{
+				task->workerid = worker;
+				task->execute_on_a_specific_worker = 1;
+			}
+		}
+		else if (arg_type == STARPU_WORKER_ORDER)
+		{
+			i++;
+			unsigned order = *(unsigned *)arglist[i];
+			if (order != 0)
+			{
+				STARPU_ASSERT_MSG(task->execute_on_a_specific_worker, "worker order only makes sense if a workerid is provided");
+				task->workerorder = order;
+			}
+		}
+		else if (arg_type == STARPU_SCHED_CTX)
+		{
+			i++;
+			task->sched_ctx = *(unsigned *)arglist[i];
+		}
+		else if (arg_type == STARPU_HYPERVISOR_TAG)
+		{
+			i++;
+			task->hypervisor_tag = *(int *)arglist[i];
+		}
+		else if (arg_type == STARPU_POSSIBLY_PARALLEL)
+		{
+			i++;
+			task->possibly_parallel = *(unsigned *)arglist[i];
+		}
+		else if (arg_type == STARPU_FLOPS)
+		{
+			i++;
+			task->flops = *(double *)arglist[i];
+		}
+		else if (arg_type == STARPU_TAG)
+		{
+			i++;
+			task->tag_id = *(starpu_tag_t *)arglist[i];
+			task->use_tag = 1;
+		}
+		else if (arg_type == STARPU_TAG_ONLY)
+		{
+			i++;
+			task->tag_id = *(starpu_tag_t *)arglist[i];
+		}
+		else if (arg_type == STARPU_NAME)
+		{
+			i++;
+			task->name = arglist[i];
+		}
+		else if (arg_type == STARPU_NODE_SELECTION_POLICY)
+		{
+			i++;
+			(void)arglist[i];
+		}
+		else
+		{
+			STARPU_ABORT_MSG("unknown/unsupported argument type");
+		}
+		i++;
+	}
+
+	if (nargs)
+	{
+		memcpy(arg_buffer_, (int *)&nargs, sizeof(nargs));
+		task->cl_arg = arg_buffer_;
+		task->cl_arg_size = arg_buffer_size_;
+	}
+	else
+	{
+		free(arg_buffer_);
+		arg_buffer_ = NULL;
+	}
+
+	int ret = starpu_task_submit(task);
+	if (ret != 0)
+	{
+		STARPU_ABORT_MSG("starpu_task_submit failed");
+	}
+}