Julia: 䟝存関数の自動再コンパむル

䜜成日 2011幎11月26日  Â·  55コメント  Â·  ゜ヌス: JuliaLang/julia

d2を呌び出す関数d1の前に関数d2を定矩しおから、d2を倉曎するず、d1はd2の叀い定矩を䜿甚したす。
これはすべおプリコンパむルされおいるためだず思いたすが、おそらくこれに぀いおのメモの譊告があるはずですか たたは、叀い定矩を新しい定矩のlongjmpに眮き換えるこずは可胜でしょうか
私は垞に党負荷をかけるずは限らないので、REPLにずっお最も重芁です

julia> function d2()
       a
       end

julia> function d()
         d2()
       end

julia> d()
in d: a not defined

julia> function d2()
       b=2
       end

julia> d()
in d: a not defined

julia> d2
Methods for generic function d2
d2() at prompt:2

julia> function d()
         d2()
       end

julia> d()
2

最も参考になるコメント

ワオ。 なんお玠晎らしい瞬間でしょう。

党おのコメント55件

これは、関数の定矩時にd2()のコヌドが生成され、その時点でd()メ゜ッドが解決されるためだず思いたす。 お気づきのずおり、 d2()は元々定矩されおいたずおりに再定矩しお、期埅どおりに機胜させるこずができたす。 理想的には、このように倉曎されたずきにd()に䟝存するものを自動的に再定矩したすが、それを可胜にするメタデヌタはありたせん。 この動䜜に぀いおの譊告をマニュアルに蚘茉できるず思いたす。 それでも修正する方が良いでしょうが、それを行うのは少し難しいず思いたす-/

誰もこれに気付かないこずを望んでいたしたが、それは私にずっお珟実的ではなかったず思いたす:)

それよりも楜しいです。 実行されるたで解決されないため、実際にJITが機胜しおいるこずを確認できたす。

julia> function f2()
       a
       end

julia> function f1()
       f2()
       end

julia> function f2()
       2
       end

julia> f1()
2

ただし、これに察凊する最善の方法はわかりたせんが、これがREPLで予期しない結果に぀ながる可胜性があるこずを恐れおいたす。 ゚ラヌを䜿甚しお劇的な方法で違いを瀺したしたが、内郚方皋匏たたは定数を倉曎した堎合の圱響を確認しようずした堎合にも発生する可胜性がありたす。

メ゜ッドが倉曎されたずきに曎新する必芁がある可胜性のある堎所には、次の2぀のタむプがありたす。

  • メ゜ッドが関数ずしお明瀺的に呌び出される堎所call / ret
  • メ゜ッドがむンラむン化されおいる堎所

前者は、関数本䜓を倉曎するだけで曎新できたす。その堎で倉曎するか、呌び出し元のサむトをアクティブに曎新しお新しい堎所を呌び出すか、叀い関数本䜓を新しいバヌゞョンにゞャンプするスタブに眮き換えるこずができたす。 、オプションで呌び出し元サむトにパッチを適甚したす。 むンラむン化するには、関数をむンラむン化した呌び出し元を远跡し、それらを再JITする必芁がありたす。

メ゜ッドがむンラむン化されおいなくおも、メ゜ッドを呌び出す関数は、メ゜ッドが倉曎された堎合に倉曎される可胜性のある型の動䜜に䟝存する可胜性があるため、実際にできるこずはコヌドを砎棄するこずだけです。 これは䞻にむンタラクティブなケヌスのためのものであるため、コヌドの再コンパむルは倧したこずではありたせん。
問題47ず同じ䜜業が必芁です。

バマヌ。 圱響を受けるのは䞻に担圓者であるため、正しいこずをゆっくり行うこずは問題ありたせん。 実行時に、これが開始されるこずはほずんどありたせん。むンタラクティブな堎合を陀いお、なぜ誰かが䜕かを定矩しおから、それを再定矩するのでしょうか。 ゜リュヌションが倚くのオヌバヌヘッドを匕き起こすこずになった堎合、おそらくそれを回すのはオプションであり、担圓者で自動的に行われるべきですか

これは珟圚未定矩であるこずを文曞化する必芁がありたす。

技術的には、これはバグではなく、未定矩の動䜜です。 メ゜ッドを再定矩するず、結果の動䜜は未定矩になりたす。 そのため、ゞュリアは珟圚行っおいるこずを含め、奜きなこずを䜕でもできたす。 メ゜ッドの再定矩時に明確に定矩された動䜜を提䟛するこずは機胜であり、バグ修正ではありたせん。 たた、未定矩の動䜜から明確に定矩された動䜜を提䟛するこずは重倧な倉曎ではないため、これがv1.0の問題であるずは確信しおいたせん。 これは、有効なv1.0コヌドを壊すこずなくv1.1で実装できたす。

AppleのLLVM / LLDBスタッフのGregClaytonは芪切にも、埋め蟌たれたシンボル情報シンボルむンポヌトからバむナリの䟝存関係を決定するために必芁な情報をlldbラむブラリ、llvmのサブプロゞェクトで匕き出す方法を文曞化しおくれたした。 バむナリによっお゚クスポヌトされたシンボルず同様に完党な䟝存関係グラフを䜜成するために必芁。

  • ゞェむ゜ン

2012幎3月31日午埌11時2分、ゞェむ゜ンE.アテンは次のように曞いおいたす。

LLDB愛奜家の皆様、

lldbラむブラリ/ラむブラリを䜿甚しお、dyldinfo -lazy_bind -exportsの出力ず同様にシンボルの2぀のリストを返すOSXで実行されおいる特定のコヌドを眮き換えるこずができるかどうか疑問に思っおいたす; ぀たり、バむナリ共有オブゞェクトたたはバンドルによっおむンポヌトおよび゚クスポヌトされたシンボルを䞀芧衚瀺する必芁がありたす。

私の望みは、lldbラむブラリを䜿甚するこずで、OSXでもLinuxず同じクラむアントコヌドを䜿甚できるようになるこずでした。 Linuxバヌゞョンのコヌドは珟圚libbfdずlibdldを䜿甚しお同じこずを行っおいたすが、埌者はほずんど愛/メンテナンスを取埗しおいたせん。

include / lldb /を調べおいたす。これは、lldbが機胜するためにこれず同じ情報むンポヌトされたシンボルリストずMach-Oファむルの゚クスポヌトされたシンボルリストが必芁なようですが、䜿甚するAPIが明確ではありたせん。 lldbのサンプルコヌドぞのすべおの提案/ポむンタは倧歓迎です

ありがずうございたした。
ゞェむ゜ン

dyldinfoが䜕をするのかわからない堎合のために、ここに䟋を瀺したす:(ただし、アドレス、セグメント、セクションではなく、シンボル名のみが必芁です

$ファむル/ tmp / sample_bundle
/ tmp / sample_bundleMach-O64ビットバンドルx86_64

$ dyldinfo -lazy_bind -export / tmp / sample_bundle

遅延バむンディング情報dyld情報のlazy_bind郚分から
セグメントセクションアドレスむンデックスdylibシンボル
__DATA __la_symbol_ptr 0x000010300x0000フラット名前空間__mm_pop_chunk
__DATA __la_symbol_ptr 0x00001038 0x0015 flat-namespace _dh_define
情報の゚クスポヌトトラむから
0x000008A0 _C_ipair
0x00000920 _init_ipair
0x00000BC0 _C_iprot
0x00000C40 _C_ipi2
0x00000CC0 _C_ipi1
0x00001040 _K_ipair_R43808f40
0x00001160 _K_ipi1_R5cb4475d
0x00001260 _K_ipi2_R5cb4475d
0x00001360 _K_iprot_Rfc8fe739
0x00001460 _majver_ipair
0x00001464 _minver_ipair

2012幎4月2日月曜日午埌3時13分、Greg [email protected]は次のように曞いおいたす。

Yes you can do this with LLDB. If you load a binary and dump its symbol table, you will see the information you want. For symbols that are lazily bound, you can look for "Trampoline" symbols:

cd lldb/test/lang/objc/foundation
make
lldb a.out
(lldb) target modules dump symtab a.out
Symtab, file = .../lldb/test/lang/objc/foundation/a.out, num_symbols = 54:
              Debug symbol
              |Synthetic symbol
              ||Externally Visible
              |||
Index   UserID DSX Type         File Address/Value Load Address       Size               Flags      Name
------- ------ --- ------------ ------------------ ------------------ ------------------ ---------- ----------------------------------
[    0]      0 D   SourceFile   0x0000000000000000                    Sibling -> [   15] 0x00640000 /Volumes/work/gclayton/Documents/src/lldb/test/lang/objc/foundation/main.m
[    1]      2 D   ObjectFile   0x000000004f79f1ca                    0x0000000000000000 0x00660001 /Volumes/work/gclayton/Documents/src/lldb/test/lang/objc/foundation/main.o
[    2]      4 D   Code         0x00000001000010f0                    0x00000000000000c0 0x000e0000 -[MyString initWithNSString:]
[    3]      8 D   Code         0x00000001000011b0                    0x0000000000000090 0x000e0000 -[MyString dealloc]
[    4]     12 D   Code         0x0000000100001240                    0x00000000000000a0 0x000e0000 -[MyString description]
[    5]     16 D   Code         0x00000001000012e0                    0x0000000000000020 0x000e0000 -[MyString descriptionPauses]
[    6]     20 D   Code         0x0000000100001300                    0x0000000000000030 0x000e0000 -[MyString setDescriptionPauses:]
[    7]     24 D   Code         0x0000000100001330                    0x0000000000000030 0x000e0000 -[MyString str_property]
[    8]     28 D   Code         0x0000000100001360                    0x0000000000000050 0x000e0000 -[MyString setStr_property:]
[    9]     32 D   Code         0x00000001000013b0                    0x0000000000000040 0x000f0000 Test_Selector
[   10]     36 D   Code         0x00000001000013f0                    0x0000000000000130 0x000f0000 Test_NSString
[   11]     40 D   Code         0x0000000100001520                    0x0000000000000120 0x000f0000 Test_MyString
[   12]     44 D   Code         0x0000000100001640                    0x00000000000001b0 0x000f0000 Test_NSArray
[   13]     48 D   Code         0x00000001000017f0                    0x00000000000000e1 0x000f0000 main
[   14]     56 D X Data         0x0000000100002680                    0x0000000000000000 0x00200000 my_global_str
[   15]     58 D   SourceFile   0x0000000000000000                    Sibling -> [   19] 0x00640000 /Volumes/work/gclayton/Documents/src/lldb/test/lang/objc/foundation/my-base.m
[   16]     60 D   ObjectFile   0x000000004f79f1ca                    0x0000000000000000 0x00660001 /Volumes/work/gclayton/Documents/src/lldb/test/lang/objc/foundation/my-base.o
[   17]     62 D   Code         0x00000001000018e0                    0x0000000000000020 0x000e0000 -[MyBase propertyMovesThings]
[   18]     66 D   Code         0x0000000100001900                    0x000000000000001f 0x000e0000 -[MyBase setPropertyMovesThings:]
[   19]     82     Data         0x0000000100002000                    0x0000000000000460 0x000e0000 pvars
[   20]     83     ObjCIVar     0x0000000100002518                    0x0000000000000148 0x001e0000 MyBase.propertyMovesThings
[   21]     84   X Data         0x0000000100002660                    0x0000000000000008 0x000f0000 NXArgc
[   22]     85   X Data         0x0000000100002668                    0x0000000000000008 0x000f0000 NXArgv
[   23]     86   X ObjCClass    0x00000001000024d8                    0x0000000000000028 0x000f0000 MyBase
[   24]     87   X ObjCClass    0x0000000100002460                    0x0000000000000028 0x000f0000 MyString
[   25]     88   X ObjCIVar     0x0000000100002510                    0x0000000000000008 0x000f0000 MyString._desc_pauses
[   26]     89   X ObjCIVar     0x0000000100002508                    0x0000000000000008 0x000f0000 MyString.date
[   27]     90   X ObjCIVar     0x0000000100002500                    0x0000000000000008 0x000f0000 MyString.str
[   28]     91   X ObjCMetaClass 0x00000001000024b0                    0x0000000000000028 0x000f0000 MyBase
[   29]     92   X ObjCMetaClass 0x0000000100002488                    0x0000000000000028 0x000f0000 MyString
[   30]     97   X Data         0x0000000100002678                    0x0000000000000008 0x000f0000 __progname
[   31]     98   X Data         0x0000000100000000                    0x00000000000010b0 0x000f0010 _mh_execute_header
[   32]     99   X Data         0x0000000100002670                    0x0000000000000008 0x000f0000 environ
[   33]    101   X Data         0x0000000100002680                    0x0000000000000000 0x000f0000 my_global_str
[   34]    102   X Code         0x00000001000010b0                    0x0000000000000040 0x000f0000 start
[   35]    103     Trampoline   0x0000000100001938                    0x0000000000000006 0x00010200 NSLog
[   36]    104   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010400 OBJC_CLASS_$_NSArray
[   37]    105   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010200 OBJC_CLASS_$_NSAutoreleasePool
[   38]    106   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010400 OBJC_CLASS_$_NSDate
[   39]    107   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010400 OBJC_CLASS_$_NSObject
[   40]    108   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010200 OBJC_CLASS_$_NSString
[   41]    109   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010400 OBJC_METACLASS_$_NSObject
[   42]    110   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010400 __CFConstantStringClassReference
[   43]    111   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010100 _objc_empty_cache
[   44]    112   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010100 _objc_empty_vtable
[   45]    113     Trampoline   0x000000010000193e                    0x0000000000000006 0x00010300 exit
[   46]    114     Trampoline   0x0000000100001920                    0x0000000000000006 0x00010100 objc_getProperty
[   47]    115     Trampoline   0x0000000100001926                    0x0000000000000006 0x00010100 objc_msgSend
[   48]    116     Trampoline   0x000000010000192c                    0x0000000000000006 0x00010100 objc_msgSendSuper2
[   49]    117   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010100 objc_msgSend_fixup
[   50]    118     Trampoline   0x0000000100001932                    0x0000000000000006 0x00010100 objc_setProperty
[   51]    119     Trampoline   0x0000000100001944                    0x0000000000000006 0x00010300 printf
[   52]    120     Trampoline   0x000000010000194a                    0x0000000000000006 0x00010300 usleep
[   53]    121   X Undefined    0x0000000000000000                    0x0000000000000000 0x00010300 dyld_stub_binder
(lldb)


All lazily bound symbols will have type Trampoline:

[   45]    113     Trampoline   0x000000010000193e                    0x0000000000000006 0x00010300 exit
[   46]    114     Trampoline   0x0000000100001920                    0x0000000000000006 0x00010100 objc_getProperty
[   47]    115     Trampoline   0x0000000100001926                    0x0000000000000006 0x00010100 objc_msgSend
[   48]    116     Trampoline   0x000000010000192c                    0x0000000000000006 0x00010100 objc_msgSendSuper2
[   50]    118     Trampoline   0x0000000100001932                    0x0000000000000006 0x00010100 objc_setProperty
[   51]    119     Trampoline   0x0000000100001944                    0x0000000000000006 0x00010300 printf
[   52]    120     Trampoline   0x000000010000194a                    0x0000000000000006 0x00010300 usleep

The other symbols that are exernal are marked with an "X" (which is a boolean flag on each symbol).

The symbols can be accessed via the SBModule:

   size_t
   SBModule::GetNumSymbols ();

   lldb::SBSymbol
   SBModule::GetSymbolAtIndex (size_t idx);

And then you can get the symbol type from each SBSymbol:

   SymbolType
   SBSymbol::GetType ();


I just added the ability to see if a symbol is externally visible:
% svn commit
Sending        include/lldb/API/SBSymbol.h
Sending        scripts/Python/interface/SBSymbol.i
Sending        source/API/SBSymbol.cpp
Transmitting file data ...
Committed revision 153893.


   bool
   SBSymbol::IsExternal();


So your flow should be:

SBDebugger::Initialize();
SBDebugger debugger(SBDebugger::Create());
SBTarget target (debugger.CreateTarget (const char *filename,
                                       const char *target_triple,
                                       const char *platform_name,
                                       bool add_dependent_modules,
                                       lldb::SBError& error));

SBFileSpec exe_file_spec (filename);
SBModule exe_module (target.FindModule(exe_file_spec));
if (exe_module.IsValid()
{
   const size_t num_symbols = exe_module. GetNumSymbols();
   for (size_t i=0; i<num_symbols; ++i)
   {
       SBSymbol symbol (exe_module. GetSymbolAtIndex(i));
       if (symbol.IsExternal())
       {
       }

       if (symbol.GetType() == lldb::eSymbolTypeTrampoline)
       {
       }
   }
}




> _______________________________________________
> lldb-dev mailing list
> [email protected]
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

2012幎4月2日月曜日の午埌4時5分、Greg [email protected]は次のように曞いおいたす。

A quick clarification on the args to CreateTarget:

"filename" is just a full path to the local object file you want to observer. "target_triple" is your <arch>-<vendor>-<os>, or something like "x86_64-apple-darwin" or "i386-pc-linux" and can be NULL if the file is only a single architecture. "platform_name" can be NULL. "add_dependent_modules" should be false, since you are only interested in seeing the one object file itself, an SBError instance  should be created and passed in.

ここでの開発リストのディスカッション https //groups.google.com/forum/ = topic / julia -dev / snnGKJul4vg。

これは驚くほど叀いスレッドを浚枫しおいたすが、codespeedベンチマヌクコヌドでこの問題の端をいちゃ぀く可胜性があるこずに気づきたした。 listTests()ずrunTests()぀の関数を含むCore.include()ファむルを繰り返し実行したす。 次に、 listTests()ずrunTests()を呌び出すだけで、新しいベンチマヌクファむルをロヌドするたびに再定矩しお呌び出すこずができたす。 私は第2局の関数を再定矩しおいないので、ここにリストされおいる問題に遭遇するこずはないず思いたすが、このようなものを再定矩するこずは、同じ「API」で耇数のファむルをロヌドするための悪い方法ですか

それらをモゞュヌルに繰り返し含める方が良いかもしれたせんが、開発リストでも提起されおいる匿名モゞュヌルの問題にぶ぀かるこずに気づきたした。 ただし、この堎合は、同じモゞュヌルを耇数回定矩しお、発生する譊告を無芖できるため、問題ない堎合がありたす。

おそらく叀いスレッドですが、盞倉わらず関連性がありたす。
おそらく別のアプロヌチは、 evalfileを䜿甚しお、ファむルに関数のタプルを「返す」こずです。 匿名モゞュヌルの問題は䜕ですか

私はこれを参照しおいたした https 

実装戊略に぀いお他に考えおいる人はいたすか 最適化されおいないASTに基づいお新しいメ゜ッドが䜜成されるたびに曎新される逆コヌルグラフを維持する単玔なスキヌムをコヌディングするこずを考えおいたした。 次に、メ゜ッドが再定矩されたずきにそのグラフをりォヌクし、再定矩された各関数の子孫のコンパむル枈みバヌゞョンを削陀したす。

これは、他の方法ず同じくらい合理的なアプロヌチです。 あなたがそれをやる気になっおいるず感じおいるなら、私は先に進んで、䜕が起こるか芋おみたしょう

呌び出し先の_execution_が呌び出し元の再コンパむルをトリガヌするずどうなりたすか

この問題を解決するず、REPLでのナヌザヌ゚クスペリ゚ンスを超えた興味深い結果がもたらされる可胜性があるこずに遅れお気付いたので、質問したす。メタプログラミングの問題に察する究極の答え、぀たり効率的な「段階的」関数の䜜成が可胜になる可胜性がありたす。 知らない人のための背景ずしおいく぀かの関数は珟圚メタプログラミングによっお実装されおいたす、特にアルゎリズムのいく぀かの偎面が重芁な方法で入力のタむプに䟝存しおいるもの---暙準的な䟋は関数本䜓のルヌプの数は、配列の次元に等しくなりたす。 通垞これを凊理する方法は、たずえば次元1ず2に察しお関数を明瀺的に定矩し、次のようなラッパヌを䜜成するこずです。

_method_cache = Dict()
function myfunction(A::AbstractArray)
    N = ndims(A)
    if !haskey(_method_cache, N)
        func = eval(<an expression that generates the function definition for N dimensions>)
        _method_cache[N] = func
    else
        func = _method_cache[N]
    end
    return func(A)
end

したがっお、4次元配列に察しお初めおmyfunctionが実行されるず、最初に4次元に固有のバヌゞョンが定矩され、それが_method_cacheに远加されおから、入力の新しい関数が評䟡されたす。 4次元配列を䜿甚したmyfunction今埌の呌び出しでは、ディクショナリから定矩を取埗しお評䟡するだけです。 _method_cacheは、Julia独自の内郚メ゜ッドテヌブルず䞊行した䞀皮の「シャドりメ゜ッドテヌブル」であり、この特定の関数のためだけに䜿甚されたす。 非公開にするために、通垞はletカプセル化されたす。

この䟋のアプロヌチは、実行に時間がかかる関数本䜓には適しおいたすが、蟞曞怜玢に必芁な時間よりも短い時間で実行される関数にはあたり適しおいたせん。たた、必芁な関数には特に適しおいたせん。むンラむン化できたす。

これを行うためのより良い方法は次のずおりです。

function myfunction(A::AbstractArray)
    bodyexpr = <an expression for the body of the function specific for N dimensions>
    f = <strong i="17">@eval</strong> begin
        function myfunction(A::$(typeof(A)))
            $bodyexpr
        end
    end
    return f(A)
end

ここで、 myfunctionするず、これらの特定の入力タむプに察しお_より具䜓的な_バヌゞョンのmyfunctionれたす。 この新しい定矩が利甚可胜になった埌にコンパむルされたコヌドは、該圓する堎合はこの新しいバヌゞョンを䜿甚したす。 䞊蚘のバヌゞョンは、より具䜓的なものをただ定矩しおいない堎合の䞀般的な「フォヌルバック」になりたす。 したがっお、これは、Julia独自の内郚メ゜ッドテヌブルメカニズムを掻甚する段階的な関数を䜜成する方法であり、したがっお、効率的なコヌドを生成するこずができたす。

珟圚、これは1぀の重倧な理由で機胜したせん。぀たり、 myfunctionず呌ばれるものはすべおすでにコンパむルされおいるため、新しい定矩に぀いおはわかりたせん。 その結果、この特定の呌び出し元は垞にevalを䜿甚しおmyfunction新しいバヌゞョンを生成したすが、これは非垞に遅くなりたす。

したがっお、トリックは呌び出し元を再コンパむルするこずですが、これは_実行の途䞭で_発生する必芁があるこずに泚意しおください。 䜕が起こるだろう

5395も参照しおください。

実際にはメ゜ッドの再定矩を䌎わないが、同様の凊理を必芁ずする抜象型に関連する問題がありたす。 考えおみたしょう

abstract A
immutable B <: A; end
immutable C <: A; end

g(x::Vector{A}) = f(x[1])

f(::B) = 1
g(A[B()])

f(::C) = 0.5
g(A[C()])

最埌の行は4602678819172646912たす。 f(::A)の型掚論が無効になったため、 gのコヌドを砎棄する必芁がありたす。

はい、それは非垞に明確です。 メ゜ッドの眮き換えは1぀の特殊なケヌスにすぎないこずを私たちは知っおいたす。 ただし、垞に新しいメ゜ッド定矩が含たれたす。

それ以来、珟圚の状況はどういうわけか曖昧になる可胜性があるようです

f() = x()
x() = 1
println(f())
x() = 2
println(f())

䞎える

1
1

䞀方

g() = y()
precompile(g, ())
y() = 1
println(g())
y() = 2
println(g())

䞎える

1
2

埌者のケヌスは、呌び出し元の再コンパむルを゚ミュレヌトするための回避策ずしお䜿甚できるようです実際には再コンパむルではないこずを私は知っおいたす。

愚かなこずを蚀おうずしおいるような気がしたすが、この問題は単䞀レベルの間接参照で解消できたせんでしたか 関数アドレスをハヌドコヌディングする代わりに、固定された堎所から怜玢しお呌び出したす。 これは、C ++たたはJava仮想関数ず同様のパフォヌマンスを発揮したせんか 次に、静的アドレスたたは動的アドレスを持぀ように関数に泚釈を付け、静的アドレスで関数を再定矩しようずするず譊告/゚ラヌが発生する可胜性がありたす。 デフォルトの機胜動䜜を蚭定するためのスむッチさえあるかもしれたせん。 私はこの蚀語に䞍慣れで、コヌドベヌスにたったく慣れおいたせんが、これが実珟可胜であるず思われる堎合は、ゞャブを䞎えるこずができるず思いたす。

@ omer4dそのアむデアの1぀の問題は、Juliaが倚くの小さな関数をむンラむン化するため、特定の関数のすべおの「䟝存関係」を怜玢する方法が必芁なこずです。

C ++のように、静的アドレスを持぀ものだけをむンラむン化できたす。 これで䞍䟿が生じるこずはありたせん。
デフォルトの動䜜ではすべおの関数に静的アドレスを䜿甚するため、むンタラクティブな開発を気にしない人はたったく圱響を受けたせん。
パフォヌマンスは気にしないがむンタラクティブな開発が必芁な人は、スむッチを䜿甚しお、デフォルトで関数アドレスを動的にするこずができたす。
察話性ずパフォヌマンスの䞡方が必芁な人は、関連する関数に泚釈を付けるこずができたすが、むンラむン化は頻繁に呌び出される短い䜎レベルの関数にのみ関連するため、倚くの䜜業は必芁ありたせん。
おそらく、デフォルトの動䜜はモゞュヌルごずに蚭定するこずもできたす。

アプロヌチが実行可胜でない理由はいく぀かあるず思いたす。 最初、
泚釈は、特にハッキングする必芁がある堎合、本圓に厄介です。
このような実装の詳现に぀いお。 泚釈を䜿甚しお2を解決する堎合
たたは3぀の問題、それらはかなり積み重なっおいきたす。 第二に、ありたせん
関数に適切な泚釈を遞択するための良い方法。 ありたせん
䜕かをむンラむン化したいかどうかず、
むンタラクティブに開発したす。 第䞉に、他の関数での型控陀
倉曎が必芁な堎合があるため、サむトを呌び出すだけではありたせん。 実際、私たちは珟圚
私たちが物事を䜜るこずができる可胜性があるよりも少ないタむプ情報を導き出す
この問題に盎面しおも安党です。

さお、数十の修食子キヌワヌドず繰り返しの手動再コンパむルを䜿甚しお蚀語でほずんどの䜜業を行う人ずしお、関数を1぀か2぀修食し、むンタラクティブな開発の数サむクル埌に再コンパむルする必芁があるこずはそれほど悪くはありたせんが、それは私だけです。 しかし、3番目のポむントに察凊するのに十分な知識がないので、蟞任したす。 再コンパむルずは、倉曎された関数の呌び出しツリヌのルヌトにゲヌムたたはアニメヌションルヌプが含たれおいる堎合、それを終了しお再起動する必芁があるため、このような゜リュヌションが実行できないのは残念だず思いたす。 =

@JeffBezanson少なくずも最初は、簡単なケヌスにおそらく最も興味があるでしょう。 eval介しおアクセスされるものたずえば、REPLプロンプトで入力されるものずは察照的に、実行䞭のコヌドが曎新されるこずはそれほど気にしたせん。 最終的には、たずえば、再定矩時に呌び出されるdisplayの正しいバヌゞョンを取埗するこずも重芁になりたす。 しかし、これにより、むンクリメンタルコンパむルにすぐに近づくこずができるず思いたす。

この問題を知っお少し驚いたのは、これを凊理するのが簡単だず思うからではなく、次のこずが期埅どおりに機胜するからです。

julia> f(a, b) = a + b
f (generic function with 1 method)

julia> g(args...) = f(args...)
g (generic function with 1 method)

julia> g(1, 2)
3

julia> f(a::Int, b::Int) = a - b
f (generic function with 2 methods)

julia> g(1, 2)
-1

線集実際、これはVararg入力の特殊なケヌスのように芋えたす.....これは、vararg関数が呌び出されるたびに再コンパむルされるこずを意味したすか それずも、必芁な堎合にのみ再コンパむルするのに十分賢いですか そしお、他の機胜を同じように扱うこずは可胜ですか

julia> f(a, b) = a + b
f (generic function with 1 method)

julia> g(a, b) = f(a, b)
g (generic function with 1 method)

julia> g(1, 2)
3

julia> f(a::Int, b::Int) = a - b
f (generic function with 2 methods)

julia> g(1, 2)
3

実際には、関数は正しい結果を返したすが、 @code_typedは間違った結果を返したす.....

julia> f(a, b) = a + b
f (generic function with 1 method)

julia> g(args...) = f(args...)
g (generic function with 1 method)

julia> g(1, 2)
3

julia> <strong i="7">@code_typed</strong> g(1, 2)
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(args::(top(apply_type))(Vararg,Any)::Any::Any)], Any[Any[],Any[Any[:args,(Int64,Int64),0]],Any[]], :(begin  # none, line 1:
        return (top(box))(Int64,(top(add_int))((top(tupleref))(args::(Int64,Int64),1)::Int64,(top(tupleref))(args::(Int64,Int64),2)::Int64))
    end::Int64))))

julia> f(a::Int, b::Int) = a - b
f (generic function with 2 methods)

julia> g(1, 2)
-1

julia> <strong i="8">@code_typed</strong> g(1, 2)
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(args::(top(apply_type))(Vararg,Any)::Any::Any)], Any[Any[],Any[Any[:args,(Int64,Int64),0]],Any[]], :(begin  # none, line 1:
        return (top(box))(Int64,(top(add_int))((top(tupleref))(args::(Int64,Int64),1)::Int64,(top(tupleref))(args::(Int64,Int64),2)::Int64))
    end::Int64))))

そしお

julia> f(a, b) = a + b
f (generic function with 1 method)

julia> g(args...) = f(args...)
g (generic function with 1 method)

julia> g(1, 2)
3

julia> f(a::Int, b::Int) = a - b
f (generic function with 2 methods)

julia> g(1, 2)
-1

julia> <strong i="12">@code_typed</strong> g(1, 2)
1-element Array{Any,1}:
 :($(Expr(:lambda, Any[:(args::(top(apply_type))(Vararg,Any)::Any::Any)], Any[Any[],Any[Any[:args,(Int64,Int64),0]],Any[]], :(begin  # none, line 1:
        return (top(box))(Int64,(top(sub_int))((top(tupleref))(args::(Int64,Int64),1)::Int64,(top(tupleref))(args::(Int64,Int64),2)::Int64))
    end::Int64))))

関数のメ゜ッドたたは関数タむプ/オブゞェクト自䜓のみに、䜕かが割り圓おられるたびに倉化する番号をむンデックス付けしお、コンパむルされた呌び出し元関数に栌玍されおいる番号぀たり、新しい構造を䜿甚しおいるかどうかを確認できるようになりたすか関数の数、これらの数倀をフィヌルドずしお保存するなどは、むンラむン化された呌び出された関数で「珟圚」のものず䞀臎したすか
もちろん倧きなパフォヌマンスペナルティなしで
たた、倉曎があった堎合は、新しいバヌゞョンをコンパむルするか、明瀺的に呌び出すこずを怜蚎しおください。

これにより、パフォヌマンスぞの圱響がランタむムに移動したすそしお、それはどこにでもありたす。これは望たしくありたせん。 必芁なのは、䟝存関係のWebを远跡し、メ゜ッドが郚分的に再定矩されたずきに圱響を受ける可胜性のあるものをすべお再コンパむルするこずです。 それはおそらく実行可胜です、それはただの_倧芏暡な_痛みです。

この問題の解決策がマクロに簡単に䞀般化できるかどうかはわかりたせんが、そうであれば、それがあればいいのですが。

したがっお、逆に、関数をむンラむン化したすべおのメ゜ッドを栌玍し、倉曎時にそれらを再コンパむルする必芁がありたす。 もちろん、珟圚の実行などをチェックしたす

ここでの難しい問題は次のずおりです。

  • あなたが蚀うようにコヌドの無効化は、生成されたコヌドで叀い関数を䜿甚するすべおの堎所を芋぀けたす。 これはおそらく、倉曎されたが呌び出し芏玄ず戻り倀の型が倉曎されおいない関数を呌び出すコヌドを再配眮できるこずを意味したす。
  • より難しい新しいメ゜ッドを定矩しおいるずきに別のタスクが実行されおいる堎合はどうなりたすか どのような状態が衚瀺されたすか 効率的に実装するのは非垞に難しいため、スタック䞊の眮換なしでそれを解決したいず考えおいたす。 私たちは、パフォヌマンスを損なうこずのない解決策があるず思いたす。

問題の解決に取り組んでいる間、私はそれが可胜かどうか興味があり、䞎えられた関数が䞊䜍の方法のいずれかで䜿甚された堎合にのみ、蚭定されたすべおの関数にフラグを远加するこずをお勧めしたすむンラむン化などむンラむン化されたメ゜ッドが再定矩されたずいう譊告を生成するため。 あいたいな譊告が機胜する方法ず同様
フラグを保存するより良い方法がない堎合は、おそらくjulia0.5のメ゜ッド/関数の新しい構造を䜿甚するこずによっお

replでこれをヒットするのはさらに簡単になり、この動䜜はマップ甚に文曞化する必芁がありたすか

julia> function f(x)
         1
       end 
f (generic function with 1 method)

julia> map(f, 1:10)
10-element Array{Int64,1}:
 1
 1
 1
 1
 1
 1
 1
 1
 1
 1

julia> function f(x)
         2
       end
WARNING: Method definition f(Any) in module Main at REPL[9]:2 overwritten at REPL[11]:2.
f (generic function with 1 method)

julia> map(f, 1:10)
10-element Array{Int64,1}:
 1
 1
 1
 1
 1
 1
 1
 1
 1
 1

それはただバニラ265です。 これはv0.6-devでたもなく修正されるこずを理解しおいただけるず思いたす:)

@vtjnashランタむムパフォヌマンスたたはメモリのトレヌドオフはありたすか

少しのメモリ140MB-> 170 MBが必芁ですが、パフォヌマンスコンパむルたたはランタむムに倧きな圱響を䞎えるこずはありたせん。 そしお、私はただあたり最適化を詊みおいたせん。

これたでのデモは楜しいです

julia> f() = 1
f (generic function with 1 method)

julia> function g(x)
    <strong i="7">@eval</strong> f() = $x # this is the correct way to write `global f() = x` (which should be a syntax error, but isn't currently)
    return @eval(f)() # use `eval` to hide the value from optimization / inlining, but the call is not inside eval
end
g (generic function with 1 method)

julia> g(2)
WARNING: Method definition f() in module Main at REPL[1]:1 overwritten at REPL[2]:2.
1

julia> g(3)
WARNING: Method definition f() in module Main at REPL[2]:2 overwritten at REPL[2]:2.
2

julia> g(4)
WARNING: Method definition f() in module Main at REPL[2]:2 overwritten at REPL[2]:2.
3

2、3、順序による4でコンパむル返さない理由であるg再定矩するこずを実行察f起こるのでは

おおたかにそうです。 蚀語セマンティクスはコンパむルを定矩しないこずに泚意しおください。したがっお、 gが解釈される順序ず、 fの再定矩がむンタヌプリタヌに衚瀺される時間ずの比范の方が正しいず蚀えたす。

了解したした。 +プリミティブを再定矩しお、䜿甚量をカりントする、もう1぀の楜しい小さなデモを次に瀺したす。

julia> add_ctr = UInt(0)
0x0000000000000000

julia> Base.:+(a::Int, b::Int) = (global add_ctr += 1; Core.Intrinsics.add_int(a, b))

julia> add_ctr
0x0000000000000016

julia> last = 0;

julia> println(Int(add_ctr - last)); last = add_ctr;
287

julia> println(Int(add_ctr - last)); last = add_ctr;
17

それはごたかしです。 +がBaseによっお䜿甚されるこずはたったくないず思うので、再コンパむルするものは䜕もありたせんでした。 svdような、REPLが衚瀺される前に少なくずも100回呌び出される必芁があるこずがわかっおいる実際の関数を再定矩したす。 それから私たちは感動するでしょう。

プロファむリング/トレヌス甚のコヌドをラむブで再むンストルメント化する機䌚は私を驚かせおいたす。

確かに。 そしお、ここで私は新しいキヌボヌドを賌入しようずしおいたした。なぜなら、シヌケンスCtrl-D; julia<Enter>はほずんど䜿い叀されおいるからです。 私はする必芁がないように芋えたす。

リリヌスノヌトに入れるのは少し難解かもしれたせんが、内包衚蚘がcollect -ing Generator構文になっおいるこずに泚意しおくださいおそらく解析レベルのものずは察照的です 0.4では- @whichはそこでは機胜したせん この䟋は、䞊蚘のvchuravyず同様に、各関数が0.5の型になったこずを考慮しおも、ちょっずした萜ずし穎です。

               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "?help" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.5.0-rc3+0 (2016-08-22 23:43 UTC)
 _/ |\__'_|_|_|\__'_|  |
|__/                   |  x86_64-linux-gnu

julia> f(x) = 1
f (generic function with 1 method)

julia> [f(x) for x in 1:5]
5-element Array{Int64,1}:
 1
 1
 1
 1
 1

julia> f(x) = 2
WARNING: Method definition f(Any) in module Main at REPL[1]:1 overwritten at REPL[3]:1.
f (generic function with 1 method)

julia> [f(x) for x in 1:5]
5-element Array{Int64,1}:
 1
 1
 1
 1
 1

julia> <strong i="9">@which</strong> [f(x) for x in 1:5]
collect(itr::Base.Generator) at array.jl:295

そうじゃないですよね

修正265に圹立ちたす

これは本圓に修正されおいたすか😲

この゜リュヌションはただ0.5.xにバックポヌトされる予定ですか

番号。

@ rapus95 、これは非垞に䟵襲的な倉曎であり、これを間違えるず、倚くのナヌザヌの

この問題の進展を芋おずおもうれしいです これにより、コンパむラがhttps://groups.google.com/forum/#!topic/julia -users / OBs0fmNmjCUで説明されおいるケヌスを最適化できるようになれば驚くべきこずです。

ワオ。 なんお玠晎らしい瞬間でしょう。

こんにちは、みんな

この修正を0.5シリヌズにバックポヌトする可胜性はありたすか それずも、0.6になるものでのみ機胜したすか

これは重倧な倉曎であり、0.6でのみ利甚可胜になりたす

これを修正するこずがどれほど玠晎らしいかを誇匵するのは難しいです。 叀い習慣は䞀生懞呜に死ぬので、私は時々ゞュリアを䞍必芁に再起動したり再構築したりしたすが、私が芚えおいるずき、それは問題を修正するための完党なゲヌムチェンゞャヌです。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡