Skip to content

mx._Native passing Ptr{Void} as parameter #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vchuravy opened this issue Nov 4, 2015 · 13 comments
Closed

mx._Native passing Ptr{Void} as parameter #15

vchuravy opened this issue Nov 4, 2015 · 13 comments

Comments

@vchuravy
Copy link
Collaborator

vchuravy commented Nov 4, 2015

I am working on a basic interface to use Julia functions to implement operators. If I see it correctly mx._Native is the operator used to create Native Operators and its expects a Ptr{Void} as info parameter [1]. That void pointer should point to a struct containing function pointers.

immutable NativeOpInfo
         forward :: Ptr{Void}
         backward :: Ptr{Void}
         infer_shape :: Ptr{Void}
         list_outputs :: Ptr{Void}
         list_arguments :: Ptr{Void}

         function NativeOpInfo(forward :: Function, backwards :: Function, infer_shape :: Function, list_outputs :: Function, list_arguments :: Function)
           f = cfunction(forward,   Void, (Ptr{Ptr{Cfloat}}, Ptr{Cint}, Ptr{Cuint}, Ptr{Cint}))
           b = cfunction(backwards, Void, (Ptr{Ptr{Cfloat}}, Ptr{Cint}, Ptr{Cuint}, Ptr{Cint}))
           i = cfunction(infer_shape, Void, (Cint, Ptr{Cint}, Ptr{Ptr{Cuint}}))
           lo = cfunction(list_outputs, Void, (Ptr{Ptr{Ptr{Cchar}}},))
           la = cfunction(list_arguments, Void, (Ptr{Ptr{Ptr{Cchar}}},))

           new(f, b, i, lo, la)
         end
       end

After creating the appropriate object I want to pass it as a Ptr to mx_.Native

mx._Native(info = pointer_from_objref(info), name = :test)
ERROR: MXNet.mx.MXError("Invalid Parameter format for info expect  but value='Ptr{Void} @0x00007fe01e46c2b0'")
 [inlined code] from /home/wallnuss/.julia/v0.4/MXNet/src/base.jl:57
 in ___Native#13__ at /home/wallnuss/.julia/v0.4/MXNet/src/symbol.jl:56

I was thinking that maybe Ptr{Void} are handled differently in MXNet.jl?

[1] native_op-inl.h

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 4, 2015

So it seems that the pointer is passed as a string from [1] to [2] ...

In Python

>>> class NumpyOpInfo(Structure):
...   _fields_ = [
...     ('a', c_int),
...   ]
... 
>>> a = NumpyOpInfo(1)
>>> hex(cast(pointer(a), c_void_p).value)
'0x7f4a92a73520'

In julia

 hex(reinterpret(UInt64, pointer_from_objref(info)))
"7fe20f35d6c0"

julia> "0x" * hex(reinterpret(UInt64, pointer_from_objref(info)))
"0x7fe20f35d6c0"

julia> mx._Native(info = bytestring("0x", hex(reinterpret(UInt, pointer_from_objref(info)))), name = :test)

signal (11): Segmentation fault
_ZN5mxnet2op12NativeOpProp4InitERKSt6vectorISt4pairISsSsESaIS4_EE at /home/wallnuss/.julia/v0.4/MXNet/deps/usr/lib/libmxnet.so (unknown line)
MXSymbolCreateAtomicSymbol at /home/wallnuss/.julia/v0.4/MXNet/deps/usr/lib/libmxnet.so (unknown line)
___Native#13__ at /home/wallnuss/.julia/v0.4/MXNet/src/base.jl:53
julia__Native_21599 at  (unknown line)

[1]python frontend
[2]backend

@tqchen
Copy link
Member

tqchen commented Nov 4, 2015

You will need to keep reference of the object you passed, so they do not went out of scope during the lifecycle of the Naive Operator

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 4, 2015

I keep a reference to the object around, so that the GC doesn't remove it. My current problem is more related with how to pass the pointer to my struct through.

@pluskid
Copy link
Member

pluskid commented Nov 4, 2015

@vchuravy I have not been able to look into this yet. Is the info object defined in the Julia side or the C++ side? I'm not sure about the current FFI of direct mapping Julia struct to C++ struct. There are some other caveat that might be relevant (or not). For example, currently passing Julia functions as backend does not support closures. See e.g. here

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 4, 2015

Direct mapping of isbits types is possible with ccall and passing in Ref{T} since 0.4 and the functions I use are closure free (currently just taking the input and returning nothing). The seqfault happens when I am casting the pointer I get to the struct, so I am probably doing something wrong (even though sizeof agrees)

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 4, 2015

The struct actually gets unpacked, the seqfault comes from calling one of the functions.

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 5, 2015

@pluskid You are right, the problem is directly calling the julia function from the C++ code.

In OpenCL.jl we handle it like this: https://github.com/JuliaGPU/OpenCL.jl/blob/f529546ac3d9aa0517e1d7e4b72856f45284d096/src/event.jl#L97

@pluskid
Copy link
Member

pluskid commented Nov 5, 2015

@vchuravy Thanks for looking into this. This sounds complicated. So that is currently the only way of handling this?

@tqchen
Copy link
Member

tqchen commented Nov 5, 2015

What I do not understand was that the kvstore callback(updater) seems to work already, what is the difference between that and this case?

@pluskid
Copy link
Member

pluskid commented Nov 5, 2015

+1, I have not really looked at the _Native API yet so I'm not sure what is the main difference / difficulty. @vchuravy can you summarize what is the main issue here?

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 5, 2015

The main issue appears to sit 40 cm in front of my monitor. I managed to get a function call through to julia following the kvstore callback example.

To make that work we will need to change the Native API but I have an PR ready for that.

This will make it work for a limited set of functions. The requirement will be that the functions don't pull in any variables outside their own closure [2] and that it won't be thread-safe [1].

[1] http://docs.julialang.org/en/latest/manual/calling-c-and-fortran-code/#thread-safety
[2] JuliaGPU/OpenCL.jl#34

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 5, 2015

@vchuravy
Copy link
Collaborator Author

vchuravy commented Nov 5, 2015

Thank you both for the discussion, it was very helpful.

@vchuravy vchuravy closed this as completed Nov 5, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants