How to call a function using remotecall_fetch ( Julia - parallel) - parallel-processing

I want to run a simple function on process 2. So I defined function like this:
julia> f(x,y) = x+y
f (generic function with 1 method)
and then I wanted to do it on process 2, but I got an error on it:
julia> remotecall_fetch(f,2,1,1)
ERROR: On worker 2:
UndefVarError: #f not defined
deserialize_datatype at ./serialize.jl:969
handle_deserialize at ./serialize.jl:674
deserialize at ./serialize.jl:634
handle_deserialize at ./serialize.jl:681
deserialize_msg at ./distributed/messages.jl:98
message_handler_loop at ./distributed/process_messages.jl:161
process_tcp_streams at ./distributed/process_messages.jl:118
#99 at ./event.jl:73
Stacktrace:
[1] #remotecall_fetch#141(::Array{Any,1}, ::Function, ::Function, ::Base.Distributed.Worker, ::Int64, ::Vararg{Int64,N} where N) at ./distributed/remotecall.jl:354
[2] remotecall_fetch(::Function, ::Base.Distributed.Worker, ::Int64, ::Vararg{Int64,N} where N) at ./distributed/remotecall.jl:346
[3] #remotecall_fetch#144(::Array{Any,1}, ::Function, ::Function, ::Int64, ::Int64, ::Vararg{Int64,N} where N) at ./distributed/remotecall.jl:367
[4] remotecall_fetch(::Function, ::Int64, ::Int64, ::Vararg{Int64,N} where N) at ./distributed/remotecall.jl:367
I know we can define function like this:
julia> #everywhere f(x,y)=x+y
and then we can get the result:
julia> remotecall_fetch(f,2,3,4)
7
Actually I don't know how can I define my functions In all processes or some of them by Include or using
.

#everywhere is the correct macro to use. For modules, just do #everywhere using MyModule and all the exported functions in module MyModule will be available to all worker processes.

Related

Difference between f(s::String) and f(::String)

What is the difference between the following two functions?
julia> one(s::String) = return 1
one (generic function with 1 method)
julia> one(::String) = return 1
one (generic function with 1 method)
Both seem to be allowed and there doesn't seem to be a difference between them. I suppose not including the v could signal to the compiler that the value of the argument is not used, but then again this is something the compiler can figure out, right? (Disclaimer: I have no idea how compilers work)
There is no difference if you don't use the argument, and yes, for the compiler this should be trivial.
You can use _ as an actual "discard argument" though, and the parser will prevent you from using it:
julia> f(_) = _ + 1
ERROR: syntax: all-underscore identifier used as rvalue around REPL[9]:1
That's useful in some situations:
julia> _, _, z = (1,2,3)
(1, 2, 3)
julia> z
3
julia> _
ERROR: all-underscore identifier used as rvalue
while
julia> x, x, z = (1,2,3)
(1, 2, 3)
julia> x
2
is slightly confusing.
More technicalities
An unused argument is preseved in IR, though:
julia> one(::String) = return 1
one (generic function with 1 method)
julia> one2(s::String) = return 1
one2 (generic function with 1 method)
julia> ir = #code_lowered one("sdf")
CodeInfo(
1 ─ return 1
)
julia> ir.slotnames
2-element Array{Symbol,1}:
Symbol("#self#")
Symbol("#unused#")
julia> ir2 = #code_lowered one2("sdf")
CodeInfo(
1 ─ return 1
)
julia> ir2.slotnames
2-element Array{Symbol,1}:
Symbol("#self#")
:s
If you ever care about slot names. I can't imagine how this would change further compilation, but it can be a corner case in metaprogramming.

Implementing a sampler with array eltype

Hooking into rand has been easier in the old days... I think I followed the description in the docs, but it doesn't seem to like a sampler returning an array:
using Random
struct Shell{N}
r0::Float64
r1::Float64
end
Base.eltype(::Type{Shell{N}}) where {N} = Array{Float64, N}
function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
# ignore the correctness of the sampling algorithm for now :)
shell = d[]
Δ = shell.r1 - shell.r0
θ = Δ .* randn(N)
r = shell.r0 .+ θ .* .√rand(N)
end
Test:
julia> rand(Shell{2}(0, 1))
2-element Array{Float64,1}:
0.5165139561555491
0.035180151872393726
julia> rand(Shell{2}(0, 1), 2)
ERROR: MethodError: no method matching Array{Float64,2}(::Array{Float64,1})
Closest candidates are:
Array{Float64,2}(::AbstractArray{S,N}) where {T, N, S} at array.jl:498
Array{Float64,2}(::UndefInitializer, ::Int64, ::Int64) where T at boot.jl:406
Array{Float64,2}(::UndefInitializer, ::Int64...) where {T, N} at boot.jl:410
...
Stacktrace:
[1] convert(::Type{Array{Float64,2}}, ::Array{Float64,1}) at ./array.jl:490
[2] setindex!(::Array{Array{Float64,2},1}, ::Array{Float64,1}, ::Int64) at ./array.jl:782
[3] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:271 [inlined]
[4] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:266 [inlined]
[5] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:279 [inlined]
[6] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:280 [inlined]
[7] rand(::Shell{2}, ::Int64) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:283
[8] top-level scope at REPL[14]:1
What am I missing?
Your definition of rand always returns an Array{Float64,1}, yet you declared that it returns Array{Float,N} (via your definition of eltype). This is what the error tells you: to put a freshly produced Vector{Float64} into the result array with eltype Array{Float64,2}, a conversion has to be made, but no such conversion is defined, hence the error.
In this case, it seems that changing the eltype definition to Base.eltype(::Type{<:Shell}} = Array{Float64, 1} would solve your problem.

Retrieve method content as an `Expr`ession

I have a function f defined as follows.
f(x, y) = 3x^2 + x*y - 2y + 1
How can I retrieve the following quote block for this method, which includes the function contents?
quote # REPL[0], line 2:
((3 * x ^ 2 + x * y) - 2y) + 1
end
As folks have mentioned in the comments, digging through the fields of the methods like this isn't a stable or officially supported API. Further, your simple example is deceiving. This isn't, in general, representative of the original code you wrote for the method. It's a simplified intermediate AST representation with single-assignment variables and drastically simplified control flow. In general, the AST it returns isn't valid top-level Julia code. It just so happens that for your simple example, it is.
That said, there is a documented way to do this. You can use code_lowered() to get access to this intermediate representation without digging through undocumented fields. This will work across Julia versions, but I don't think there are official guarantees on the stability of the intermediate representation yet. Here's a slightly more complicated example:
julia> f(X) = for elt in X; println(elt); end
f (generic function with 1 method)
julia> code_lowered(f)[1]
LambdaInfo template for f(X) at REPL[17]:1
:(begin
nothing
SSAValue(0) = X
#temp# = (Base.start)(SSAValue(0))
4:
unless !((Base.done)(SSAValue(0),#temp#)) goto 13
SSAValue(1) = (Base.next)(SSAValue(0),#temp#)
elt = (Core.getfield)(SSAValue(1),1)
#temp# = (Core.getfield)(SSAValue(1),2) # line 1:
(Main.println)(elt)
11:
goto 4
13:
return
end)
julia> code_lowered(f)[1] == methods(f).ms[1].lambda_template
true
If you really want to see the code exactly as it was written, the best way is to use the embedded file and line information and refer to the original source. Note that this is precisely the manner in which Gallium.jl (Julia's debugger) finds the source to display as it steps through functions. It's undocumented, but you can even access the REPL history for functions defined interactively. See how Gallium does it through here.
First, retrieve the method using methods(f).
julia> methods(f)
# 1 method for generic function "f":
f(x, y) at REPL[1]:1
julia> methods(f).ms
1-element Array{Method,1}:
f(x, y) at REPL[1]:1
julia> method = methods(f).ms[1]
f(x, y) at REPL[1]:1
From here, retrieving the Expression is straightforward; simply use the lambda_template attribute of the method.
julia> method.lambda_template
LambdaInfo template for f(x, y) at REPL[1]:1
:(begin
nothing
return ((3 * x ^ 2 + x * y) - 2 * y) + 1
end)
Edit: This does not work in Julia v0.6+!

Julia: Passing Multiple Arguments to Anonymous Functions

In the Julia Manual under the Anonymous Functions section one of the examples that is offered is (x,y,z)->2x+y-z.
Could someone please show me how one would pass a set of arguments to this function?
Say x=(1,2,3); y=(2,3,4); z=(1,3,5).
If you define x,y and z to be arrays then you can just call the function and pass them in:
fun = (x,y,z)->2x+y-z
x=[1,2,3]
y=[2,3,4]
z=[1,3,5]
fun(x, y, z)
giving the result:
3-element Array{Int64,1}:
3
4
5
But if you want to do this with tuples, as per your example, you will need to use map:
x=(1,2,3)
y=(2,3,4)
z=(1,3,5)
map(fun, x, y, z)
this gives the same result, but this time as a tuple:
(3, 4, 5)
This is because the *, + and - operators are not defined for tuples so the formula 2x+y-z can't work. Using map gets around this by calling the function multiple times passing in scalars.
You have to assign the anonymous function to a variable, in order to call it.
julia> fun = (x,y,z)->2x+y-z
(anonymous function)
julia> fun((1,2,3),(2,3,4),(1,3,5))
ERROR: no method *(Int64, (Int64,Int64,Int64))
in anonymous at none:1
It does not work, because the tuples you set for x, does not implement the * function.

Method for common values in two lists

Does Ruby has a method I could use when I have 2 arrays (lists) and I want to get an array (list) of only the values common to both arrays? Like this..
a = [1,2,3]
b = [3,4,5]
=> the method would return [3]
And the other way around, values that are "unique" in those arrays (lists).
a = [1,2,3]
b = [3,4,5]
=> the method would return [1,2,4,5]
AND : a & b
There are no XOR method for arrays in Ruby, so you may do it via another methods. Here are 2 ways:
XOR : (a | b) - (a & b)
XOR : (a + b) - (a & b) # this result can have duplicates!
XOR : (a - b) | (b - a)
XOR : (a - b) + (b - a) # this result can have duplicates!
The words you are looking for are intersection and symmetric difference. AFAIK it's this in Ruby:
[1,2,3] & [3,4,5] = [3]
[1,2,3] ^ [3,4,5] = [1,2,4,5]

Resources