Skip to content
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

macro threadcall does not accept Ref arguments #30864

Closed
felipenoris opened this issue Jan 28, 2019 · 10 comments
Closed

macro threadcall does not accept Ref arguments #30864

felipenoris opened this issue Jan 28, 2019 · 10 comments

Comments

@felipenoris
Copy link
Contributor

felipenoris commented Jan 28, 2019

While working on a driver for Oracle, I experimented with macro threadcall on this function.

# int dpiConn_create(const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiConn **conn)
function dpiConn_create(context_handle::Ptr{Cvoid}, user::String, password::String, connect_string::String, common_params_ref::Ref{OraCommonCreateParams}, conn_create_params_ref::Ref{OraConnCreateParams}, dpi_conn_handle_ref::Ref{Ptr{Cvoid}})
    userNameLength = sizeof(user)
    passwordLength = sizeof(password)
    connectStringLength = sizeof(connect_string)

    @threadcall((:dpiConn_create, libdpi), OraResult, (Ptr{Cvoid}, Ptr{UInt8}, UInt32, Ptr{UInt8}, UInt32, Ptr{UInt8}, UInt32, Ref{OraCommonCreateParams}, Ref{OraConnCreateParams}, Ref{Ptr{Cvoid}}), context_handle, user, userNameLength, password, passwordLength, connect_string, connectStringLength, common_params_ref, conn_create_params_ref, dpi_conn_handle_ref)
end

All Ref arguments are outputs of the C API.

When I run this function, I get an error:

ERROR: LoadError: argument is an abstract type; size is indeterminate. 
Stacktrace:
 [1] _mapreduce at ./reduce.jl:316 [inlined]
 [2] _mapreduce_dim at ./reducedim.jl:308 [inlined]
 [3] #mapreduce#548 at ./reducedim.jl:304 [inlined]
 [4] mapreduce at ./reducedim.jl:304 [inlined]
 [5] _sum at ./reducedim.jl:653 [inlined]
 [6] #sum#551 at ./reducedim.jl:649 [inlined]
 [7] sum at ./reducedim.jl:649 [inlined]
 [8] do_threadcall(::Ptr{Nothing}, ::Type, ::Array{Any,1}, ::Array{Any,1}) at ./threadcall.jl:67
 [9] dpiConn_create(::Ptr{Nothing}, ::String, ::String, ::String, ::Base.RefValue{Oracle.OraCommonCreateParams}, ::Base.RefValue{Oracle.OraConnCreateParams}, ::Base.RefValue{Ptr{Nothing}}) at ./threadcall.jl:52
 [10] Oracle.Connection(::Oracle.Context, ::String, ::String, ::String, ::Oracle.CommonCreateParams, ::Oracle.ConnCreateParams) at /home/felipenoris/Documents/src/Oracle.jl/src/connection.jl:60
 [11] main() at /home/felipenoris/Documents/src/Oracle.jl/src/connection.jl:76
 [12] top-level scope at /home/felipenoris/Documents/src/Oracle.jl/benchmarks/thread.jl:38
 [13] include at ./boot.jl:326 [inlined]
 [14] include_relative(::Module, ::String) at ./loading.jl:1041
 [15] include(::Module, ::String) at ./Base.jl:29
 [16] include(::String) at ./client.jl:418
 [17] top-level scope at REPL[3]:1
in expression starting at /home/felipenoris/Documents/src/Oracle.jl/benchmarks/thread.jl:38

After digging into the code, I found that the problem is the Ref type:

julia> sizeof(Ref{Ptr{Cvoid}})
ERROR: argument is an abstract type; size is indeterminate
Stacktrace:
 [1] sizeof(::Type) at ./essentials.jl:416
 [2] top-level scope at none:0

julia> sizeof(Ref{UInt8})
ERROR: argument is an abstract type; size is indeterminate
Stacktrace:
 [1] sizeof(::Type) at ./essentials.jl:416
 [2] top-level scope at none:0
@martinholters
Copy link
Member

Base.RefValue?

@felipenoris
Copy link
Contributor Author

felipenoris commented Jan 28, 2019

I didn't know Base.RefValue existed. But if I change the implementation to use it, I get another error:

ArgumentError: threadcall requires isbits argument types

Which is strange, because a regular pointer Ptr{Cvoid} is not a bits type also.

I would argue that @threadcall should have the same requirements as the ccall function.

@amcostant
Copy link

amcostant commented Jul 17, 2019

I am having a similar problem with my code.

function pdiff(b1::Array{Basic,1}, b2::Basic)
    dfdx = Array{Basic}(undef,length(b1))
    Threads.@threads for i = 1:length(b1)
        a = Basic()
        ret = @threadcall((:basic_diff, libsymengine), Int, (Ref{Basic}, Ref{Basic}, Ref{Basic}), a, b1[i], b2)
        dfdx[i] = a
    end
    return dfdx
end

I get the following error


julia> pdiff(ex,a)

Error thrown in threaded loop on thread 16: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 5: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 9: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 2: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 13: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 12: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 8: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 6: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 15: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 1: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 0: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 19: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 20: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 10: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 14: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 3: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 7: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 18: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 21: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 17: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 11: ErrorException("argument is an abstract type; size is indeterminate")
Error thrown in threaded loop on thread 4: ErrorException("argument is an abstract type; size is indeterminate")10000-element Array{Basic,1}:
 #undef
 #undef
 #undef
   ⋮   
 #undef
 #undef
 #undef

julia> 

@StefanKarpinski
Copy link
Member

@threadcall was always a stopgap until we could actually run Julia code on multiple threads, which we can now do. In 1.3, full threading functionality will no longer be experimental, and @threadcall will be completely vestigial. To that end it's probably not worth fixing it, but perhaps it can be reimplemented in terms of the new proper threading functionality.

@amcostant
Copy link

@StefanKarpinski How would you recommend I implement the above code in V1.3? Thanks!

@StefanKarpinski
Copy link
Member

Once some version of #32600 is merged, you would use that macro. I would rewrite your code to show this but I'm a little confused about why you're using both @threads and @threadcall. Can you explain what your code is trying to do?

@amcostant
Copy link

I think I misunderstood how @threadcall works.
I got the code to work like this and ran it

function pdiff(b1::Array{Basic,1}, b2::Basic)
    dfdx = Array{Basic}(undef,length(b1))
    Threads.@threads for i = 1:length(b1)
        a = Basic()
        ret = ccall((:basic_diff, libsymengine), Int, (Ref{Basic}, Ref{Basic}, Ref{Basic}), a, b1[i], b2)
        dfdx[i] = a
    end
    return dfdx
end

and on my laptop I saw a O(n^1/2) improvment with number of threads, but on my desktop I saw a decrease in performance with adding cores.
this might be helpful
desktop:

julia> versioninfo()
Julia Version 1.1.1
Commit 55e36cc308 (2019-05-16 04:10 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, haswell)
Environment:
  JULIA_NUM_THREADS = 44

image

My laptop has the same Julia version and runs on windows.
Any help would be greatly appreciated.

@StefanKarpinski
Copy link
Member

Help with performance is more appropriate for discourse.

@felipenoris
Copy link
Contributor Author

Closing, as I understand the new thread api will replace threadcall.

@felipenoris
Copy link
Contributor Author

@threadcall was always a stopgap until we could actually run Julia code on multiple threads, which we can now do. In 1.3, full threading functionality will no longer be experimental, and @threadcall will be completely vestigial. To that end it's probably not worth fixing it, but perhaps it can be reimplemented in terms of the new proper threading functionality.

@StefanKarpinski , sorry about bringing this up again, I just would like to make a quick check on this, given that 1.4 is out and the Threading funcionality is more mature. Is it still true that threadcall is an "old" thing and we should use replace it with the new Threading API? What makes me think about using threadcall is that there's no setup for the user since Julia starts with 4 libuv threads (based on the docs), but 1 julia thread unless the user specifies a JULIA_NUM_THREADS.

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

4 participants