HidemotoNakada / julia-works

0 stars 0 forks source link

macro でなんか隠蔽できないか #6

Open HidemotoNakada opened 1 year ago

HidemotoNakada commented 1 year ago
@actor 
struct Pinger end

@remote
function ping(p::Ping, v::Vector{UInt8})::Vector{UInt8} 
     v
end 

p = @start Pinger()
fetch(ping(p, buf))

みたいに書けると嬉しいか?

HidemotoNakada commented 1 year ago
@remote function xxx(xx)
を
そのままの関数とリモートリファレンスを引数にした関数の2つにバラす。

まずは変換後のイメージを実装してみよう。メッセージはタプルにして、関数名と引数にする。

HidemotoNakada commented 1 year ago

動いた。あとは、

@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 を書く。

HidemotoNakada commented 1 year ago

だいたいできた。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
HidemotoNakada commented 1 year ago

いや、まだだ。動いていない。メソッドエラーが出る。

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)
HidemotoNakada commented 1 year ago

こーどはこれ。

struct Echo <: Actor 
    id::Integer
end

@remote function ping(a::Echo, v::Vector{UInt8}) 
    v
end
HidemotoNakada commented 1 year ago

macroexpand の結果。たしかになんかへんだ。

quote
    function ping(a::ActorRef, v::Vector{UInt8}; )
        v
    end
    function ping(a::ActorRef, v::Vector{UInt8}; )
        callOn(a, (ping, [:v]))
    end
end
HidemotoNakada commented 1 year ago

いろいろ間違っていた。直した。

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
HidemotoNakada commented 1 year ago

性能もちゃんと上がっている。これで一応論文が書けるか。

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
HidemotoNakada commented 1 year ago

よく考えたら ActorRefを型で就職しないといけないのではないか。ActorRef{A} のような感じにしないとまずい? 複数のActor型に対して同じarity の関数を定義すると良くないことが起こりそうな気がする。 でも、実はほとんど問題はおきないような気もする。