xji*_*xji 5 profiling compilation read-eval-print-loop julia
我已经阅读了相当多的文档和问题,但我仍然对此感到困惑.
在文档的Profiling部分,建议首先在REPL中运行一次目标函数,以便在分析之前编译它.但是,如果脚本相当复杂并且打算在命令行中运行,接受参数怎么办?当julia进程完成并且我第二次运行脚本时,是否再次执行编译?像/sf/answers/2942853441/这样的帖子,Julia每次编译脚本?给出相互矛盾的答案.当朱莉娅不断发展时,它们似乎也老了.
在我看来,第二次运行所需的时间与我的经验中的第一次运行完全相同.启动时间很长.我该如何优化这样的程序?添加__precompile__()似乎根本没有改变执行时间.
另外,当我想描述这样一个程序时,我该怎么办?关于分析的所有资源都在REPL中讨论这样做.
我有点不同意我的同事。在绝对有效的情况下,将依赖于运行julia脚本。例如,当您具有脚本管道(例如matlab,python等)时,您需要在所有脚本的中间位置插入julia脚本,并从Shell脚本控制整个管道。但是,无论用例是什么,说“只使用REPL”都不是这个问题的正确答案,即使不能提出“有效”方案,这仍然是一个值得直接回答而不是回答的问题。解决方法。
我确实同意,拥有适当代码的解决方案是将需要预编译的所有关键内容都包装到模块中,并且仅将最外部的命令保留在脚本的顶层。无论如何,这与Matlab或C ++世界并不太相似,在那儿您应该编写透彻的函数,并且只将脚本/主要函数视为某种非常简短的顶级入口点,其工作就是简单地准备初始环境,然后相应地运行那些更专门的功能。
这是我的意思的示例:
# in file 'myscript.jl'
push!( LOAD_PATH, "./" )
import MyPrecompiledModule
println( "Hello from the script. The arguments passed into it were $ARGS" )
MyPrecompiledModule.exportedfun()
Run Code Online (Sandbox Code Playgroud)
# in file 'MyPrecompiledModule.jl' (e.g. in the same directory as myscript.jl)
__precompile__()
module MyPrecompiledModule
export exportedfun;
function innerfun()
println("Hello from MyPrecompiledModule.innerfun");
end
function exportedfun()
innerfun()
print("Hello from MyPrecompiledModule.exportedfun");
end
end
Run Code Online (Sandbox Code Playgroud)
在上述情况下,MyPrecompiledModule脚本中将使用的已编译版本(如果不存在该版本,则将在您首次运行该脚本时进行编译),因此,编译的任何优化都不会在结束时丢失脚本,但最终还是得到一个独立的julia脚本,您可以将其用作bash shell脚本管道过程的一部分,也可以将参数传递给该脚本。然后,myscript.jl脚本仅在必要时将它们传递给导入的模块函数,然后执行您不特别关心它们是否已被编译/优化的任何其他命令,例如执行基准测试,提供脚本使用说明等。
如果我错了,请纠正我,但听起来你已经写了一些很长的脚本,比如说,myfile.jl然后从你的操作系统命令行调用julia myfile.jl args...。它是否正确?另外,听起来好像myfile.jl没有定义太多函数,而只是一系列命令。它是否正确?如果是这样,那么正如对该问题的评论中所建议的那样,这不是 Julia 的典型工作流程,原因有二:
1)从命令行调用julia,即julia myfile.jl args...相当于打开一个REPL,include在 上运行命令myfile.jl,然后关闭REPL。的初始调用include将编译 中的操作所需的任何方法myfile.jl,这需要时间。但由于您是从命令行运行的,因此一旦include完成,REPL 就会自动关闭,并且所有已编译的代码都会被丢弃。这就是 DNF 的意思,他说推荐的工作流程是在单个 REPL 会话中工作,并且在完成当天工作之前不要关闭它,或者除非您故意想要重新编译正在使用的所有方法。
2) 即使您在单个 REPL 会话中工作,将您所做的几乎所有事情包装在函数中也非常重要(这与 Matlab 等语言的工作流程非常不同)。如果您这样做,Julia 将为每个函数编译专门针对您正在使用的输入参数类型的方法。这本质上就是 Julia 速度快的原因。方法编译一次后,它在整个 REPL 会话中仍然可用,但在关闭 REPL 时会被丢弃。重要的是,如果您不将操作包装在函数中,则不会发生这种专门的编译,因此您可能会看到非常慢的代码。在 Julia,我们称之为“在全球范围内工作”。请注意,Julia 的这一功能鼓励一种将任务分解为许多小型专用函数的编码风格,而不是由 1000 行代码组成的庞然大物。出于多种原因,这是一个好主意。(在我自己的代码库中,许多函数都是单行,大多数是 5 行或更少)
如果您在 Julia 工作,以上两点对于了解您来说绝对至关重要。但是,一旦您对它们感到满意,我建议您实际上将所有函数放入module中,然后在需要时从活动的 REPL 会话中调用您的模块。这还有一个额外的优点,您只需__precompile__()在模块顶部添加一条语句,然后 julia 将预编译该模块中的一些(但不一定是全部)代码。执行此操作后,关闭 REPL 时模块中的预编译代码不会消失,因为它存储在硬盘驱动器上的 .ji 文件中。因此,您可以启动一个新的 REPL 会话,输入using MyModule,您的预编译代码将立即可用。仅当您更改模块的内容时才需要重新编译(这一切都会自动发生)。
| 归档时间: |
|
| 查看次数: |
1199 次 |
| 最近记录: |