Open HidemotoNakada opened 1 year ago
@remote function xxx(xx)
を
そのままの関数とリモートリファレンスを引数にした関数の2つにバラす。
まずは変換後のイメージを実装してみよう。メッセージはタプルにして、関数名と引数にする。
動いた。あとは、
@remote function ping(a::Echo, v::Vector{UInt8})
v
end
を
function ping(a::Echo, v::Vector{UInt8})
v
end
function ping(ref::ActorRef, v::Vector{UInt8})
callOn(ref, (ping, (v,)))
end
の2つに展開するマクロ remote を書く。
だいたいできた。Actorのサブクラスチェックがまだうまくできない。
macro remote(fdef)
d = splitdef(fdef)
original = combinedef(d)
if (! (typeof(d[:args][1]) <: Expr )) || # check the first argument type
d[:args][1].head != :(::) # || # cannot eval in a macro
# !(eval(:($(d[:args][1].args[2]))) <: Actor)
println(stderr, "the first argument should be Actor")
original
else
ar_var = d[:args][1].args[1]
d[:args][1].args[2] = :ActorRef
name = d[:name]
args = [typeof(arg) <: Expr ? arg.args[1] : arg for arg in d[:args][2:end]]
argtuple = Expr(:tuple, args...)
d[:body] = :(callOn($ar_var, ($name, $args)) )
remoteCall = combinedef(d)
quote
$(esc(original))
$(esc(remoteCall))
end
end
end
いや、まだだ。動いていない。メソッドエラーが出る。
nakada@Hecatoncheires julia-works % mpiexecjl -np 2 julia actor-test-mpi3.jl --hooked
ping , typeof(ping), [:v], Vector{Symbol}
MethodError(ping, (Echo(0), :v), 0x0000000000007ef8)
こーどはこれ。
struct Echo <: Actor
id::Integer
end
@remote function ping(a::Echo, v::Vector{UInt8})
v
end
macroexpand の結果。たしかになんかへんだ。
quote
function ping(a::ActorRef, v::Vector{UInt8}; )
v
end
function ping(a::ActorRef, v::Vector{UInt8}; )
callOn(a, (ping, [:v]))
end
end
いろいろ間違っていた。直した。
macro remote(fdef)
d = splitdef(fdef)
original = combinedef(d)
if (! (typeof(d[:args][1]) <: Expr )) || # check the first argument type
d[:args][1].head != :(::) # || # cannot eval in a macro
# !(eval(:($(d[:args][1].args[2]))) <: Actor)
println(stderr, "the first argument should be Actor")
original
else
(arg_name, arg_type, is_splat, default) = splitarg(d[:args][1])
# d[:args][1].args[2] = :ActorRef
d[:args][1] = combinearg(arg_name, :ActorRef, is_splat, default)
name = d[:name]
args = [typeof(arg) <: Expr ? arg.args[1] : arg for arg in d[:args][2:end]]
argtuple = Expr(:tuple, args...)
d[:body] = :(callOn($arg_name, ($name, $argtuple)) )
remoteCall = combinedef(d)
quote
$(esc(original))
$(esc(remoteCall))
end
end
end
性能もちゃんと上がっている。これで一応論文が書けるか。
nakada@Hecatoncheires julia-works % mpiexecjl -np 2 julia actor-test-mpi3.jl --hooked
1024 100 0.88683625 sec 0.00021507337265616963 GBs
1024 100 0.588467958 sec 0.0003241210684257001 GBs
10240 100 0.927244584 sec 0.0020570070353870084 GBs
102400 100 1.317823667 sec 0.014473473808180589 GBs
1048576 100 1.676561833 sec 0.11649585249743663 GBs
10485760 100 2.306427333 sec 0.8468183549748108 GBs
104857600 100 4.534627334 sec 4.3071345364055444 GBs
nakada@Hecatoncheires julia-works % mpiexecjl -np 2 julia actor-test-mpi3.jl
1024 100 0.549744208 sec 0.0003469520196950397 GBs
1024 100 0.593425917 sec 0.00032141309945728236 GBs
10240 100 0.931433583 sec 0.002047755919073942 GBs
102400 100 1.313765542 sec 0.014518181302798243 GBs
1048576 100 1.744074792 sec 0.11198630981646572 GBs
10485760 100 3.96832925 sec 0.49217816288807187 GBs
104857600 100 29.472782792 sec 0.6626876782501007 GBs
よく考えたら ActorRefを型で就職しないといけないのではないか。ActorRef{A} のような感じにしないとまずい? 複数のActor型に対して同じarity の関数を定義すると良くないことが起こりそうな気がする。 でも、実はほとんど問題はおきないような気もする。
みたいに書けると嬉しいか?