IntelLabs / ParallelAccelerator.jl

The ParallelAccelerator package, part of the High Performance Scripting project at Intel Labs
BSD 2-Clause "Simplified" License
294 stars 32 forks source link

Passing user-defined data types between C and Julia #42

Closed ChunlingHu closed 8 years ago

ChunlingHu commented 8 years ago

source code

using ParallelAccelerator

type newType
    w::Vector{Float64}
    b::Float64
end
@acc function evaluate(f::newType, X::AbstractMatrix)
    if f.b != 0
    X = X + f.b
    end
    return X
end

function main(m::Int, n::Int)
    X = Array(Float64, m, n)
    W = Array(Float64, m)
    fill!(X, 5)
    fill!(W, 3)
    b = 1.0
    f = newType(W,b)
    evaluate(f, X)
    println("done")
end
main(100, 200)
ninegua commented 8 years ago

This fails in CGen. Unfortunately, it's not possible to support passing values of arbitrary type between Julia and C. We definitely need a better error message in this case.

jsreeram commented 8 years ago

If the problem is the user-defined type, then simple cases like this one should be easy to handle. (Simple meaning fields have a type that is one of {primitive, array[T], tuple[T1,T2..]} where T, T1, T2 are also simple) via translating to a struct. You could also support constructors.

ninegua commented 8 years ago

It is not that we cannot translate a user defined type to C, which actually works for the above example. The trouble is the interface between Julia and C, and how we can pass Julia object to C and back. Julia doc http://julia.readthedocs.org/en/release-0.4/manual/calling-c-and-fortran-code/#mapping-c-types-to-julia indicates that composite types are indeed difficult to handle, since Julia objects do not necessarily map directly to C's object layout.

Besides, we are using j2c_arrays instead of Julia arrays. Converting a Julia object of the newType above to a C struct that has a j2c_array field is indeed non-trivial.

jsreeram commented 8 years ago

Sorry, I misread the example. Yes if the type crosses the C boundary then it gets a little more complicated. Let's say cgen generates the definition for this struct (struct NewType). So there are at least two problems 1) At rutime you have to figure out the offsets for each of the fields in the Julia object and populate the fields of the native arg struct. This would be hard without VM support.

What I would do, is to instead make cgen recursively flatten all such args. So cgen would generate void evaluate(j2c_array& w, double b...). We already know how to pass these args. Then in the body, simply have a stack-allocated instance of struct NewType f and set f.w and f.b to w and b. Would this work?

2) Anything involving HashCodes still has the usual problems. Not sure how one would solve that.

ninegua commented 8 years ago

We are making good progress in supporting native thread backend, so unless there is a strong request to expand CGen's coverage, I'm closing this issue for now.