Просмотр исходного кода

Julia: Handle scalar parameters.

Pierre Huchant лет назад: 5
Родитель
Сommit
d1841519fb

+ 33 - 7
julia/StarPU.jl/src/StarPU.jl

@@ -473,7 +473,7 @@ mutable struct StarpuTask
     handles :: Vector{StarpuDataHandle}
     handle_pointers :: Vector{StarpuDataHandlePointer}
     synchronous :: Bool
-    cl_arg :: Union{Ref, Cvoid}
+    cl_arg # type depends on codelet
 
     c_task :: Ptr{Cvoid}
 
@@ -483,7 +483,7 @@ mutable struct StarpuTask
 
         Creates a new task which will run the specified codelet on handle buffers and cl_args data
     """
-    function StarpuTask(; cl :: Union{Cvoid, StarpuCodelet} = nothing, handles :: Vector{StarpuDataHandle} = StarpuDataHandle[], cl_arg :: Union{Ref, Cvoid} = nothing)
+    function StarpuTask(; cl :: Union{Cvoid, StarpuCodelet} = nothing, handles :: Vector{StarpuDataHandle} = StarpuDataHandle[], cl_arg = [])
 
         if (cl == nothing)
             error("\"cl\" field can't be empty when creating a StarpuTask")
@@ -493,7 +493,16 @@ mutable struct StarpuTask
 
         output.cl = cl
         output.handles = handles
-        output.cl_arg = cl_arg
+
+        # handle scalar_parameters
+        codelet_name = cl.cpu_func
+        scalar_parameters = CODELETS_SCALARS[codelet_name]
+        nb_scalar_required = length(scalar_parameters)
+        nb_scalar_provided = length(cl_arg)
+        if (nb_scalar_provided != nb_scalar_required)
+            error("$nb_scalar_provided scalar parameters provided but $nb_scalar_required are required by $codelet_name.")
+        end
+        output.cl_arg = create_param_struct_from_clarg(codelet_name, cl_arg)
 
         output.synchronous = false
         output.handle_pointers = StarpuDataHandlePointer[]
@@ -513,6 +522,23 @@ mutable struct StarpuTask
 
 end
 
+function create_param_struct_from_clarg(codelet_name, cl_arg)
+    struct_params_name = CODELETS_PARAMS_STRUCT[codelet_name]
+    nb_scalar_provided = length(cl_arg)
+    create_struct_param_str = "output = $struct_params_name("
+    for i in 1:nb_scalar_provided-1
+        arg = cl_arg[i]
+        create_struct_param_str *= "$arg, "
+        end
+    if (nb_scalar_provided > 0)
+        arg = cl_arg[nb_scalar_provided]
+        create_struct_param_str *= "$arg"
+    end
+    create_struct_param_str *= ")"
+    eval(Meta.parse(create_struct_param_str))
+    return output
+end
+
 """
     Structure used to update fields of the real C task structure 
 """
@@ -539,8 +565,8 @@ mutable struct StarpuTaskTranslator
             output.cl_arg = C_NULL
             output.cl_arg_size = 0
         else
-            output.cl_arg = pointer_from_objref(task.cl_arg) #TODO : Libc.malloc and cl_arg_free set to 1 ? but it should be done only when submitting
-            output.cl_arg_size = sizeof(eltype(task.cl_arg))
+            output.cl_arg = pointer_from_objref(task.cl_arg)
+            output.cl_arg_size = sizeof(task.cl_arg)
         end
 
         return output
@@ -815,7 +841,7 @@ end
     Creates and submits an asynchronous task running cl Codelet function.
     Ex : @starpu_async_cl cl(handle1, handle2)
 """
-macro starpu_async_cl(expr,modes)
+macro starpu_async_cl(expr,modes,cl_arg=[])
 
     if (!isa(expr, Expr) || expr.head != :call)
         error("Invalid task submit syntax")
@@ -839,7 +865,7 @@ macro starpu_async_cl(expr,modes)
     handles = Expr(:vect, expr.args[2:end]...)
     #dump(handles)
     quote
-        task = StarpuTask(cl = $(esc(cl)), handles = $(esc(handles)))
+        task = StarpuTask(cl = $(esc(cl)), handles = $(esc(handles)), cl_arg=cl_arg)
         starpu_task_submit(task)
     end
 end

+ 44 - 31
julia/StarPU.jl/src/compiler/c.jl

@@ -1,5 +1,3 @@
-
-
 """
     Returns the list of instruction that will be added before for loop of shape
         "for for_index_var in set ..."
@@ -56,12 +54,7 @@ function add_for_loop_declarations(expr :: StarpuExpr)
     return apply(func_to_apply, expr)
 end
 
-
-
-
-
 function transform_to_cpu_kernel(expr :: StarpuExprFunction)
-
     output = add_for_loop_declarations(expr)
     output = substitute_args(output)
     output = substitute_func_calls(output)
@@ -71,7 +64,20 @@ function transform_to_cpu_kernel(expr :: StarpuExprFunction)
     return output
 end
 
+function generate_c_struct_param_declaration(funcname)
+    scalar_parameters = CODELETS_SCALARS[funcname]
+    struct_params_name = CODELETS_PARAMS_STRUCT[funcname]
+
+    output = "struct $struct_params_name {\n"
+    for p in scalar_parameters
+        arg_name = p[1]
+        arg_type = p[2]
+        output *= "\t" * starpu_type_traduction(arg_type) * " $arg_name;\n"
+    end
+    output *= "};\n\n"
 
+    return output
+end
 
 function flatten_blocks(expr :: StarpuExpr)
 
@@ -130,46 +136,55 @@ end
 
 
 function substitute_args(expr :: StarpuExprFunction)
-
     new_body = expr.body
     func_id = rand_string()
     buffer_arg_name = Symbol("buffers_", func_id)
     cl_arg_name = Symbol("cl_arg_", func_id)
-    post = false
     function_start_affectations = StarpuExpr[]
 
+    buffer_id = 1
+    scalar_id = 1
+
+    # get scalar parameters and structure name
+    scalar_parameters = CODELETS_SCALARS[string(expr.func)]
+    struct_params_name = CODELETS_PARAMS_STRUCT[string(expr.func)]
+
     for i in (1 : length(expr.args))
 
         var_id = rand_string()
         ptr = Symbol(:ptr_, var_id)
         var_name = ptr
-        
+
         if (expr.args[i].typ <: Vector)
             func_interface = :STARPU_VECTOR_GET_PTR
+            type_in_arg = eltype(expr.args[i].typ)
+            new_affect = starpu_parse( :($ptr :: Ptr{$type_in_arg} = $func_interface($buffer_arg_name[$buffer_id])) )
+            push!(function_start_affectations, new_affect)
+            new_body = substitute_argument_usage(new_body, buffer_id, buffer_arg_name, expr.args[i].name, var_name)
+            buffer_id += 1
         elseif (expr.args[i].typ <: Matrix)
             func_interface = :STARPU_MATRIX_GET_PTR
             ld_name = Symbol("ld_", var_id)
-            post_affect = starpu_parse( :($ld_name :: UInt32 = STARPU_MATRIX_GET_LD($buffer_arg_name[$i])) )
-            post=true
-            
-        elseif (expr.args[i].typ <: Float32)
-            func_interface = :STARPU_VARIABLE_GET_PTR
-            var_name = Symbol("scal_", var_id)
-            post_affect = starpu_parse( :($var_name :: Float32 = ($ptr[0])) )
-            post = true
-            
-        end
-        #else
-            #error("Task arguments must be either vector or matrix (got $(expr.args[i].typ))") #TODO : cl_args, variable ?
-        #end
-
-        type_in_arg = eltype(expr.args[i].typ)
-        new_affect = starpu_parse( :($ptr :: Ptr{$type_in_arg} = $func_interface($buffer_arg_name[$i])) )
-        push!(function_start_affectations, new_affect)
-        if (post)
+            post_affect = starpu_parse( :($ld_name :: UInt32 = STARPU_MATRIX_GET_LD($buffer_arg_name[$buffer_id])) )
+            type_in_arg = eltype(expr.args[i].typ)
+            new_affect = starpu_parse( :($ptr :: Ptr{$type_in_arg} = $func_interface($buffer_arg_name[$buffer_id])) )
+            push!(function_start_affectations, new_affect)
+            push!(function_start_affectations, post_affect)
+            new_body = substitute_argument_usage(new_body, buffer_id, buffer_arg_name, expr.args[i].name, var_name)
+            buffer_id += 1
+        elseif (expr.args[i].typ <: Number || expr.args[i].typ <: AbstractChar)
+            type_in_arg = eltype(expr.args[i].typ)
+            field_name = scalar_parameters[scalar_id][1]
+            var_name = field_name
+            post_affect = starpu_parse( :($var_name :: $type_in_arg = *($ptr).$field_name))
+            new_affect = starpu_parse( :($ptr :: Ptr{$struct_params_name} = $cl_arg_name))
+            push!(function_start_affectations, new_affect)
             push!(function_start_affectations, post_affect)
+            scalar_id += 1
+        else
+            error("Task arguments must be either vector or matrix or scalr (got $(expr.args[i].typ))")
         end
-        new_body = substitute_argument_usage(new_body, i, buffer_arg_name, expr.args[i].name, var_name)
+
 
     end
 
@@ -183,8 +198,6 @@ function substitute_args(expr :: StarpuExprFunction)
     return StarpuExprFunction(expr.ret_type, expr.func, new_args, new_body)
 end
 
-
-
 func_substitution = Dict(
     :width => :STARPU_MATRIX_GET_NY,
     :height => :STARPU_MATRIX_GET_NX,

+ 11 - 16
julia/StarPU.jl/src/compiler/expressions.jl

@@ -1,3 +1,14 @@
+global starpu_type_traduction_dict = Dict(
+    Int32 => "int32_t",
+    UInt32 => "uint32_t",
+    Float32 => "float",
+    Int64 => "int64_t",
+    UInt64 => "uint64_t",
+    Float64 => "double",
+    Nothing => "void"
+)
+export starpu_type_traduction_dict
+
 
 #======================================================
                 AFFECTATION
@@ -841,22 +852,6 @@ function starpu_parse_typed(x :: Expr)
     return StarpuExprTypedExpr(expr, typ)
 end
 
-
-
-
-
-starpu_type_traduction_dict = Dict(
-    Int32 => "int32_t",
-    UInt32 => "uint32_t",
-    Float32 => "float",
-    Int64 => "int64_t",
-    UInt64 => "uint64_t",
-    Float64 => "double",
-    Nothing => "void"
-)
-
-
-
 function starpu_type_traduction(x)
     if x <: Array
         return starpu_type_traduction_array(x)

+ 35 - 0
julia/StarPU.jl/src/compiler/file_generation.jl

@@ -95,6 +95,11 @@ global CPU_CODELETS=Dict{String,String}()
 export CUDA_CODELETS
 global CUDA_CODELETS=Dict{String,String}()
 
+export CODELETS_SCALARS
+global CODELETS_SCALARS=Dict{String,Any}()
+export CODELETS_PARAMS_STRUCT
+global CODELETS_PARAMS_STRUCT=Dict{String,Any}()
+
 """
 	    Executes @cuda_kernel and @cpu_kernel
         """
@@ -102,6 +107,7 @@ macro codelet(x)
     parsed = starpu_parse(x)
     name=string(x.args[1].args[1].args[1]);
     dump(name)
+    parse_scalar_parameters(parsed, name)
     cpu_expr = transform_to_cpu_kernel(parsed)
     prekernel, kernel = transform_to_cuda_kernel(parsed)
     generated_cpu_kernel_file_name=string("genc_",string(x.args[1].args[1].args[1]),".c")
@@ -113,6 +119,7 @@ macro codelet(x)
             kernel_file = open($(esc(generated_cpu_kernel_file_name)), "w")
             @debugprint "generating " $(generated_cpu_kernel_file_name)
             print(kernel_file, $(esc(cpu_kernel_file_start)))
+            print(kernel_file, generate_c_struct_param_declaration($name))
             print(kernel_file, $cpu_expr)
             close(kernel_file)
             CPU_CODELETS[$name]=$name
@@ -132,3 +139,31 @@ macro codelet(x)
         #global starpu_task_library_name
     end
 end
+
+function parse_scalar_parameters(expr :: StarpuExprFunction, name::String)
+    scalar_parameters = []
+    for i in (1 : length(expr.args))
+        type = expr.args[i].typ
+        if (type <: Number || type <: AbstractChar)
+            push!(scalar_parameters, (expr.args[i].name, type))
+        end
+    end
+
+    CODELETS_SCALARS[name] = scalar_parameters
+
+    # declare structure carrying scalar parameters
+    struct_params_name = Symbol("params_", rand_string())
+    structure_decl_str = "mutable struct " * "$struct_params_name\n"
+    for p in scalar_parameters
+        structure_decl_str *= "$(p[1])::$(p[2])\n"
+    end
+    structure_decl_str *= "end"
+    eval(Meta.parse(structure_decl_str))
+
+    # add structure type to dictionnary
+    add_to_dict_str = "starpu_type_traduction_dict[$struct_params_name] = \"struct $struct_params_name\""
+    eval(Meta.parse(add_to_dict_str))
+
+    # save structure name
+    CODELETS_PARAMS_STRUCT[name] = struct_params_name
+end